[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 /** 2 * @license React 3 * react-dom.development.js 4 * 5 * Copyright (c) Facebook, Inc. and its affiliates. 6 * 7 * This source code is licensed under the MIT license found in the 8 * LICENSE file in the root directory of this source tree. 9 */ 10 (function (global, factory) { 11 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) : 12 typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) : 13 (global = global || self, factory(global.ReactDOM = {}, global.React)); 14 }(this, (function (exports, React) { 'use strict'; 15 16 var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; 17 18 var suppressWarning = false; 19 function setSuppressWarning(newSuppressWarning) { 20 { 21 suppressWarning = newSuppressWarning; 22 } 23 } // In DEV, calls to console.warn and console.error get replaced 24 // by calls to these methods by a Babel plugin. 25 // 26 // In PROD (or in packages without access to React internals), 27 // they are left as they are instead. 28 29 function warn(format) { 30 { 31 if (!suppressWarning) { 32 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 33 args[_key - 1] = arguments[_key]; 34 } 35 36 printWarning('warn', format, args); 37 } 38 } 39 } 40 function error(format) { 41 { 42 if (!suppressWarning) { 43 for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { 44 args[_key2 - 1] = arguments[_key2]; 45 } 46 47 printWarning('error', format, args); 48 } 49 } 50 } 51 52 function printWarning(level, format, args) { 53 // When changing this logic, you might want to also 54 // update consoleWithStackDev.www.js as well. 55 { 56 var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; 57 var stack = ReactDebugCurrentFrame.getStackAddendum(); 58 59 if (stack !== '') { 60 format += '%s'; 61 args = args.concat([stack]); 62 } // eslint-disable-next-line react-internal/safe-string-coercion 63 64 65 var argsWithFormat = args.map(function (item) { 66 return String(item); 67 }); // Careful: RN currently depends on this prefix 68 69 argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it 70 // breaks IE9: https://github.com/facebook/react/issues/13610 71 // eslint-disable-next-line react-internal/no-production-logging 72 73 Function.prototype.apply.call(console[level], console, argsWithFormat); 74 } 75 } 76 77 var FunctionComponent = 0; 78 var ClassComponent = 1; 79 var IndeterminateComponent = 2; // Before we know whether it is function or class 80 81 var HostRoot = 3; // Root of a host tree. Could be nested inside another node. 82 83 var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. 84 85 var HostComponent = 5; 86 var HostText = 6; 87 var Fragment = 7; 88 var Mode = 8; 89 var ContextConsumer = 9; 90 var ContextProvider = 10; 91 var ForwardRef = 11; 92 var Profiler = 12; 93 var SuspenseComponent = 13; 94 var MemoComponent = 14; 95 var SimpleMemoComponent = 15; 96 var LazyComponent = 16; 97 var IncompleteClassComponent = 17; 98 var DehydratedFragment = 18; 99 var SuspenseListComponent = 19; 100 var ScopeComponent = 21; 101 var OffscreenComponent = 22; 102 var LegacyHiddenComponent = 23; 103 var CacheComponent = 24; 104 var TracingMarkerComponent = 25; 105 106 // ----------------------------------------------------------------------------- 107 108 var enableClientRenderFallbackOnTextMismatch = true; // TODO: Need to review this code one more time before landing 109 // the react-reconciler package. 110 111 var enableNewReconciler = false; // Support legacy Primer support on internal FB www 112 113 var enableLazyContextPropagation = false; // FB-only usage. The new API has different semantics. 114 115 var enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber 116 117 var enableSuspenseAvoidThisFallback = false; // Enables unstable_avoidThisFallback feature in Fizz 118 // React DOM Chopping Block 119 // 120 // Similar to main Chopping Block but only flags related to React DOM. These are 121 // grouped because we will likely batch all of them into a single major release. 122 // ----------------------------------------------------------------------------- 123 // Disable support for comment nodes as React DOM containers. Already disabled 124 // in open source, but www codebase still relies on it. Need to remove. 125 126 var disableCommentsAsDOMContainers = true; // Disable javascript: URL strings in href for XSS protection. 127 // and client rendering, mostly to allow JSX attributes to apply to the custom 128 // element's object properties instead of only HTML attributes. 129 // https://github.com/facebook/react/issues/11347 130 131 var enableCustomElementPropertySupport = false; // Disables children for <textarea> elements 132 var warnAboutStringRefs = true; // ----------------------------------------------------------------------------- 133 // Debugging and DevTools 134 // ----------------------------------------------------------------------------- 135 // Adds user timing marks for e.g. state updates, suspense, and work loop stuff, 136 // for an experimental timeline tool. 137 138 var enableSchedulingProfiler = true; // Helps identify side effects in render-phase lifecycle hooks and setState 139 140 var enableProfilerTimer = true; // Record durations for commit and passive effects phases. 141 142 var enableProfilerCommitHooks = true; // Phase param passed to onRender callback differentiates between an "update" and a "cascading-update". 143 144 var allNativeEvents = new Set(); 145 /** 146 * Mapping from registration name to event name 147 */ 148 149 150 var registrationNameDependencies = {}; 151 /** 152 * Mapping from lowercase registration names to the properly cased version, 153 * used to warn in the case of missing event handlers. Available 154 * only in true. 155 * @type {Object} 156 */ 157 158 var possibleRegistrationNames = {} ; // Trust the developer to only use possibleRegistrationNames in true 159 160 function registerTwoPhaseEvent(registrationName, dependencies) { 161 registerDirectEvent(registrationName, dependencies); 162 registerDirectEvent(registrationName + 'Capture', dependencies); 163 } 164 function registerDirectEvent(registrationName, dependencies) { 165 { 166 if (registrationNameDependencies[registrationName]) { 167 error('EventRegistry: More than one plugin attempted to publish the same ' + 'registration name, `%s`.', registrationName); 168 } 169 } 170 171 registrationNameDependencies[registrationName] = dependencies; 172 173 { 174 var lowerCasedName = registrationName.toLowerCase(); 175 possibleRegistrationNames[lowerCasedName] = registrationName; 176 177 if (registrationName === 'onDoubleClick') { 178 possibleRegistrationNames.ondblclick = registrationName; 179 } 180 } 181 182 for (var i = 0; i < dependencies.length; i++) { 183 allNativeEvents.add(dependencies[i]); 184 } 185 } 186 187 var canUseDOM = !!(typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined'); 188 189 var hasOwnProperty = Object.prototype.hasOwnProperty; 190 191 /* 192 * The `'' + value` pattern (used in in perf-sensitive code) throws for Symbol 193 * and Temporal.* types. See https://github.com/facebook/react/pull/22064. 194 * 195 * The functions in this module will throw an easier-to-understand, 196 * easier-to-debug exception with a clear errors message message explaining the 197 * problem. (Instead of a confusing exception thrown inside the implementation 198 * of the `value` object). 199 */ 200 // $FlowFixMe only called in DEV, so void return is not possible. 201 function typeName(value) { 202 { 203 // toStringTag is needed for namespaced types like Temporal.Instant 204 var hasToStringTag = typeof Symbol === 'function' && Symbol.toStringTag; 205 var type = hasToStringTag && value[Symbol.toStringTag] || value.constructor.name || 'Object'; 206 return type; 207 } 208 } // $FlowFixMe only called in DEV, so void return is not possible. 209 210 211 function willCoercionThrow(value) { 212 { 213 try { 214 testStringCoercion(value); 215 return false; 216 } catch (e) { 217 return true; 218 } 219 } 220 } 221 222 function testStringCoercion(value) { 223 // If you ended up here by following an exception call stack, here's what's 224 // happened: you supplied an object or symbol value to React (as a prop, key, 225 // DOM attribute, CSS property, string ref, etc.) and when React tried to 226 // coerce it to a string using `'' + value`, an exception was thrown. 227 // 228 // The most common types that will cause this exception are `Symbol` instances 229 // and Temporal objects like `Temporal.Instant`. But any object that has a 230 // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this 231 // exception. (Library authors do this to prevent users from using built-in 232 // numeric operators like `+` or comparison operators like `>=` because custom 233 // methods are needed to perform accurate arithmetic or comparison.) 234 // 235 // To fix the problem, coerce this object or symbol value to a string before 236 // passing it to React. The most reliable way is usually `String(value)`. 237 // 238 // To find which value is throwing, check the browser or debugger console. 239 // Before this exception was thrown, there should be `console.error` output 240 // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the 241 // problem and how that type was used: key, atrribute, input value prop, etc. 242 // In most cases, this console output also shows the component and its 243 // ancestor components where the exception happened. 244 // 245 // eslint-disable-next-line react-internal/safe-string-coercion 246 return '' + value; 247 } 248 249 function checkAttributeStringCoercion(value, attributeName) { 250 { 251 if (willCoercionThrow(value)) { 252 error('The provided `%s` attribute is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', attributeName, typeName(value)); 253 254 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 255 } 256 } 257 } 258 function checkKeyStringCoercion(value) { 259 { 260 if (willCoercionThrow(value)) { 261 error('The provided key is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', typeName(value)); 262 263 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 264 } 265 } 266 } 267 function checkPropStringCoercion(value, propName) { 268 { 269 if (willCoercionThrow(value)) { 270 error('The provided `%s` prop is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', propName, typeName(value)); 271 272 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 273 } 274 } 275 } 276 function checkCSSPropertyStringCoercion(value, propName) { 277 { 278 if (willCoercionThrow(value)) { 279 error('The provided `%s` CSS property is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', propName, typeName(value)); 280 281 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 282 } 283 } 284 } 285 function checkHtmlStringCoercion(value) { 286 { 287 if (willCoercionThrow(value)) { 288 error('The provided HTML markup uses a value of unsupported type %s.' + ' This value must be coerced to a string before before using it here.', typeName(value)); 289 290 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 291 } 292 } 293 } 294 function checkFormFieldValueStringCoercion(value) { 295 { 296 if (willCoercionThrow(value)) { 297 error('Form field values (value, checked, defaultValue, or defaultChecked props)' + ' must be strings, not %s.' + ' This value must be coerced to a string before before using it here.', typeName(value)); 298 299 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 300 } 301 } 302 } 303 304 // A reserved attribute. 305 // It is handled by React separately and shouldn't be written to the DOM. 306 var RESERVED = 0; // A simple string attribute. 307 // Attributes that aren't in the filter are presumed to have this type. 308 309 var STRING = 1; // A string attribute that accepts booleans in React. In HTML, these are called 310 // "enumerated" attributes with "true" and "false" as possible values. 311 // When true, it should be set to a "true" string. 312 // When false, it should be set to a "false" string. 313 314 var BOOLEANISH_STRING = 2; // A real boolean attribute. 315 // When true, it should be present (set either to an empty string or its name). 316 // When false, it should be omitted. 317 318 var BOOLEAN = 3; // An attribute that can be used as a flag as well as with a value. 319 // When true, it should be present (set either to an empty string or its name). 320 // When false, it should be omitted. 321 // For any other value, should be present with that value. 322 323 var OVERLOADED_BOOLEAN = 4; // An attribute that must be numeric or parse as a numeric. 324 // When falsy, it should be removed. 325 326 var NUMERIC = 5; // An attribute that must be positive numeric or parse as a positive numeric. 327 // When falsy, it should be removed. 328 329 var POSITIVE_NUMERIC = 6; 330 331 /* eslint-disable max-len */ 332 var ATTRIBUTE_NAME_START_CHAR = ":A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD"; 333 /* eslint-enable max-len */ 334 335 var ATTRIBUTE_NAME_CHAR = ATTRIBUTE_NAME_START_CHAR + "\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040"; 336 var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$'); 337 var illegalAttributeNameCache = {}; 338 var validatedAttributeNameCache = {}; 339 function isAttributeNameSafe(attributeName) { 340 if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) { 341 return true; 342 } 343 344 if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) { 345 return false; 346 } 347 348 if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) { 349 validatedAttributeNameCache[attributeName] = true; 350 return true; 351 } 352 353 illegalAttributeNameCache[attributeName] = true; 354 355 { 356 error('Invalid attribute name: `%s`', attributeName); 357 } 358 359 return false; 360 } 361 function shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag) { 362 if (propertyInfo !== null) { 363 return propertyInfo.type === RESERVED; 364 } 365 366 if (isCustomComponentTag) { 367 return false; 368 } 369 370 if (name.length > 2 && (name[0] === 'o' || name[0] === 'O') && (name[1] === 'n' || name[1] === 'N')) { 371 return true; 372 } 373 374 return false; 375 } 376 function shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag) { 377 if (propertyInfo !== null && propertyInfo.type === RESERVED) { 378 return false; 379 } 380 381 switch (typeof value) { 382 case 'function': // $FlowIssue symbol is perfectly valid here 383 384 case 'symbol': 385 // eslint-disable-line 386 return true; 387 388 case 'boolean': 389 { 390 if (isCustomComponentTag) { 391 return false; 392 } 393 394 if (propertyInfo !== null) { 395 return !propertyInfo.acceptsBooleans; 396 } else { 397 var prefix = name.toLowerCase().slice(0, 5); 398 return prefix !== 'data-' && prefix !== 'aria-'; 399 } 400 } 401 402 default: 403 return false; 404 } 405 } 406 function shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag) { 407 if (value === null || typeof value === 'undefined') { 408 return true; 409 } 410 411 if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag)) { 412 return true; 413 } 414 415 if (isCustomComponentTag) { 416 417 return false; 418 } 419 420 if (propertyInfo !== null) { 421 422 switch (propertyInfo.type) { 423 case BOOLEAN: 424 return !value; 425 426 case OVERLOADED_BOOLEAN: 427 return value === false; 428 429 case NUMERIC: 430 return isNaN(value); 431 432 case POSITIVE_NUMERIC: 433 return isNaN(value) || value < 1; 434 } 435 } 436 437 return false; 438 } 439 function getPropertyInfo(name) { 440 return properties.hasOwnProperty(name) ? properties[name] : null; 441 } 442 443 function PropertyInfoRecord(name, type, mustUseProperty, attributeName, attributeNamespace, sanitizeURL, removeEmptyString) { 444 this.acceptsBooleans = type === BOOLEANISH_STRING || type === BOOLEAN || type === OVERLOADED_BOOLEAN; 445 this.attributeName = attributeName; 446 this.attributeNamespace = attributeNamespace; 447 this.mustUseProperty = mustUseProperty; 448 this.propertyName = name; 449 this.type = type; 450 this.sanitizeURL = sanitizeURL; 451 this.removeEmptyString = removeEmptyString; 452 } // When adding attributes to this list, be sure to also add them to 453 // the `possibleStandardNames` module to ensure casing and incorrect 454 // name warnings. 455 456 457 var properties = {}; // These props are reserved by React. They shouldn't be written to the DOM. 458 459 var reservedProps = ['children', 'dangerouslySetInnerHTML', // TODO: This prevents the assignment of defaultValue to regular 460 // elements (not just inputs). Now that ReactDOMInput assigns to the 461 // defaultValue property -- do we need this? 462 'defaultValue', 'defaultChecked', 'innerHTML', 'suppressContentEditableWarning', 'suppressHydrationWarning', 'style']; 463 464 reservedProps.forEach(function (name) { 465 properties[name] = new PropertyInfoRecord(name, RESERVED, false, // mustUseProperty 466 name, // attributeName 467 null, // attributeNamespace 468 false, // sanitizeURL 469 false); 470 }); // A few React string attributes have a different name. 471 // This is a mapping from React prop names to the attribute names. 472 473 [['acceptCharset', 'accept-charset'], ['className', 'class'], ['htmlFor', 'for'], ['httpEquiv', 'http-equiv']].forEach(function (_ref) { 474 var name = _ref[0], 475 attributeName = _ref[1]; 476 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty 477 attributeName, // attributeName 478 null, // attributeNamespace 479 false, // sanitizeURL 480 false); 481 }); // These are "enumerated" HTML attributes that accept "true" and "false". 482 // In React, we let users pass `true` and `false` even though technically 483 // these aren't boolean attributes (they are coerced to strings). 484 485 ['contentEditable', 'draggable', 'spellCheck', 'value'].forEach(function (name) { 486 properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty 487 name.toLowerCase(), // attributeName 488 null, // attributeNamespace 489 false, // sanitizeURL 490 false); 491 }); // These are "enumerated" SVG attributes that accept "true" and "false". 492 // In React, we let users pass `true` and `false` even though technically 493 // these aren't boolean attributes (they are coerced to strings). 494 // Since these are SVG attributes, their attribute names are case-sensitive. 495 496 ['autoReverse', 'externalResourcesRequired', 'focusable', 'preserveAlpha'].forEach(function (name) { 497 properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty 498 name, // attributeName 499 null, // attributeNamespace 500 false, // sanitizeURL 501 false); 502 }); // These are HTML boolean attributes. 503 504 ['allowFullScreen', 'async', // Note: there is a special case that prevents it from being written to the DOM 505 // on the client side because the browsers are inconsistent. Instead we call focus(). 506 'autoFocus', 'autoPlay', 'controls', 'default', 'defer', 'disabled', 'disablePictureInPicture', 'disableRemotePlayback', 'formNoValidate', 'hidden', 'loop', 'noModule', 'noValidate', 'open', 'playsInline', 'readOnly', 'required', 'reversed', 'scoped', 'seamless', // Microdata 507 'itemScope'].forEach(function (name) { 508 properties[name] = new PropertyInfoRecord(name, BOOLEAN, false, // mustUseProperty 509 name.toLowerCase(), // attributeName 510 null, // attributeNamespace 511 false, // sanitizeURL 512 false); 513 }); // These are the few React props that we set as DOM properties 514 // rather than attributes. These are all booleans. 515 516 ['checked', // Note: `option.selected` is not updated if `select.multiple` is 517 // disabled with `removeAttribute`. We have special logic for handling this. 518 'multiple', 'muted', 'selected' // NOTE: if you add a camelCased prop to this list, 519 // you'll need to set attributeName to name.toLowerCase() 520 // instead in the assignment below. 521 ].forEach(function (name) { 522 properties[name] = new PropertyInfoRecord(name, BOOLEAN, true, // mustUseProperty 523 name, // attributeName 524 null, // attributeNamespace 525 false, // sanitizeURL 526 false); 527 }); // These are HTML attributes that are "overloaded booleans": they behave like 528 // booleans, but can also accept a string value. 529 530 ['capture', 'download' // NOTE: if you add a camelCased prop to this list, 531 // you'll need to set attributeName to name.toLowerCase() 532 // instead in the assignment below. 533 ].forEach(function (name) { 534 properties[name] = new PropertyInfoRecord(name, OVERLOADED_BOOLEAN, false, // mustUseProperty 535 name, // attributeName 536 null, // attributeNamespace 537 false, // sanitizeURL 538 false); 539 }); // These are HTML attributes that must be positive numbers. 540 541 ['cols', 'rows', 'size', 'span' // NOTE: if you add a camelCased prop to this list, 542 // you'll need to set attributeName to name.toLowerCase() 543 // instead in the assignment below. 544 ].forEach(function (name) { 545 properties[name] = new PropertyInfoRecord(name, POSITIVE_NUMERIC, false, // mustUseProperty 546 name, // attributeName 547 null, // attributeNamespace 548 false, // sanitizeURL 549 false); 550 }); // These are HTML attributes that must be numbers. 551 552 ['rowSpan', 'start'].forEach(function (name) { 553 properties[name] = new PropertyInfoRecord(name, NUMERIC, false, // mustUseProperty 554 name.toLowerCase(), // attributeName 555 null, // attributeNamespace 556 false, // sanitizeURL 557 false); 558 }); 559 var CAMELIZE = /[\-\:]([a-z])/g; 560 561 var capitalize = function (token) { 562 return token[1].toUpperCase(); 563 }; // This is a list of all SVG attributes that need special casing, namespacing, 564 // or boolean value assignment. Regular attributes that just accept strings 565 // and have the same names are omitted, just like in the HTML attribute filter. 566 // Some of these attributes can be hard to find. This list was created by 567 // scraping the MDN documentation. 568 569 570 ['accent-height', 'alignment-baseline', 'arabic-form', 'baseline-shift', 'cap-height', 'clip-path', 'clip-rule', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'dominant-baseline', 'enable-background', 'fill-opacity', 'fill-rule', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-name', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'horiz-adv-x', 'horiz-origin-x', 'image-rendering', 'letter-spacing', 'lighting-color', 'marker-end', 'marker-mid', 'marker-start', 'overline-position', 'overline-thickness', 'paint-order', 'panose-1', 'pointer-events', 'rendering-intent', 'shape-rendering', 'stop-color', 'stop-opacity', 'strikethrough-position', 'strikethrough-thickness', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-decoration', 'text-rendering', 'underline-position', 'underline-thickness', 'unicode-bidi', 'unicode-range', 'units-per-em', 'v-alphabetic', 'v-hanging', 'v-ideographic', 'v-mathematical', 'vector-effect', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'word-spacing', 'writing-mode', 'xmlns:xlink', 'x-height' // NOTE: if you add a camelCased prop to this list, 571 // you'll need to set attributeName to name.toLowerCase() 572 // instead in the assignment below. 573 ].forEach(function (attributeName) { 574 var name = attributeName.replace(CAMELIZE, capitalize); 575 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty 576 attributeName, null, // attributeNamespace 577 false, // sanitizeURL 578 false); 579 }); // String SVG attributes with the xlink namespace. 580 581 ['xlink:actuate', 'xlink:arcrole', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type' // NOTE: if you add a camelCased prop to this list, 582 // you'll need to set attributeName to name.toLowerCase() 583 // instead in the assignment below. 584 ].forEach(function (attributeName) { 585 var name = attributeName.replace(CAMELIZE, capitalize); 586 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty 587 attributeName, 'http://www.w3.org/1999/xlink', false, // sanitizeURL 588 false); 589 }); // String SVG attributes with the xml namespace. 590 591 ['xml:base', 'xml:lang', 'xml:space' // NOTE: if you add a camelCased prop to this list, 592 // you'll need to set attributeName to name.toLowerCase() 593 // instead in the assignment below. 594 ].forEach(function (attributeName) { 595 var name = attributeName.replace(CAMELIZE, capitalize); 596 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty 597 attributeName, 'http://www.w3.org/XML/1998/namespace', false, // sanitizeURL 598 false); 599 }); // These attribute exists both in HTML and SVG. 600 // The attribute name is case-sensitive in SVG so we can't just use 601 // the React name like we do for attributes that exist only in HTML. 602 603 ['tabIndex', 'crossOrigin'].forEach(function (attributeName) { 604 properties[attributeName] = new PropertyInfoRecord(attributeName, STRING, false, // mustUseProperty 605 attributeName.toLowerCase(), // attributeName 606 null, // attributeNamespace 607 false, // sanitizeURL 608 false); 609 }); // These attributes accept URLs. These must not allow javascript: URLS. 610 // These will also need to accept Trusted Types object in the future. 611 612 var xlinkHref = 'xlinkHref'; 613 properties[xlinkHref] = new PropertyInfoRecord('xlinkHref', STRING, false, // mustUseProperty 614 'xlink:href', 'http://www.w3.org/1999/xlink', true, // sanitizeURL 615 false); 616 ['src', 'href', 'action', 'formAction'].forEach(function (attributeName) { 617 properties[attributeName] = new PropertyInfoRecord(attributeName, STRING, false, // mustUseProperty 618 attributeName.toLowerCase(), // attributeName 619 null, // attributeNamespace 620 true, // sanitizeURL 621 true); 622 }); 623 624 // and any newline or tab are filtered out as if they're not part of the URL. 625 // https://url.spec.whatwg.org/#url-parsing 626 // Tab or newline are defined as \r\n\t: 627 // https://infra.spec.whatwg.org/#ascii-tab-or-newline 628 // A C0 control is a code point in the range \u0000 NULL to \u001F 629 // INFORMATION SEPARATOR ONE, inclusive: 630 // https://infra.spec.whatwg.org/#c0-control-or-space 631 632 /* eslint-disable max-len */ 633 634 var isJavaScriptProtocol = /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*\:/i; 635 var didWarn = false; 636 637 function sanitizeURL(url) { 638 { 639 if (!didWarn && isJavaScriptProtocol.test(url)) { 640 didWarn = true; 641 642 error('A future version of React will block javascript: URLs as a security precaution. ' + 'Use event handlers instead if you can. If you need to generate unsafe HTML try ' + 'using dangerouslySetInnerHTML instead. React was passed %s.', JSON.stringify(url)); 643 } 644 } 645 } 646 647 /** 648 * Get the value for a property on a node. Only used in DEV for SSR validation. 649 * The "expected" argument is used as a hint of what the expected value is. 650 * Some properties have multiple equivalent values. 651 */ 652 function getValueForProperty(node, name, expected, propertyInfo) { 653 { 654 if (propertyInfo.mustUseProperty) { 655 var propertyName = propertyInfo.propertyName; 656 return node[propertyName]; 657 } else { 658 // This check protects multiple uses of `expected`, which is why the 659 // react-internal/safe-string-coercion rule is disabled in several spots 660 // below. 661 { 662 checkAttributeStringCoercion(expected, name); 663 } 664 665 if ( propertyInfo.sanitizeURL) { 666 // If we haven't fully disabled javascript: URLs, and if 667 // the hydration is successful of a javascript: URL, we 668 // still want to warn on the client. 669 // eslint-disable-next-line react-internal/safe-string-coercion 670 sanitizeURL('' + expected); 671 } 672 673 var attributeName = propertyInfo.attributeName; 674 var stringValue = null; 675 676 if (propertyInfo.type === OVERLOADED_BOOLEAN) { 677 if (node.hasAttribute(attributeName)) { 678 var value = node.getAttribute(attributeName); 679 680 if (value === '') { 681 return true; 682 } 683 684 if (shouldRemoveAttribute(name, expected, propertyInfo, false)) { 685 return value; 686 } // eslint-disable-next-line react-internal/safe-string-coercion 687 688 689 if (value === '' + expected) { 690 return expected; 691 } 692 693 return value; 694 } 695 } else if (node.hasAttribute(attributeName)) { 696 if (shouldRemoveAttribute(name, expected, propertyInfo, false)) { 697 // We had an attribute but shouldn't have had one, so read it 698 // for the error message. 699 return node.getAttribute(attributeName); 700 } 701 702 if (propertyInfo.type === BOOLEAN) { 703 // If this was a boolean, it doesn't matter what the value is 704 // the fact that we have it is the same as the expected. 705 return expected; 706 } // Even if this property uses a namespace we use getAttribute 707 // because we assume its namespaced name is the same as our config. 708 // To use getAttributeNS we need the local name which we don't have 709 // in our config atm. 710 711 712 stringValue = node.getAttribute(attributeName); 713 } 714 715 if (shouldRemoveAttribute(name, expected, propertyInfo, false)) { 716 return stringValue === null ? expected : stringValue; // eslint-disable-next-line react-internal/safe-string-coercion 717 } else if (stringValue === '' + expected) { 718 return expected; 719 } else { 720 return stringValue; 721 } 722 } 723 } 724 } 725 /** 726 * Get the value for a attribute on a node. Only used in DEV for SSR validation. 727 * The third argument is used as a hint of what the expected value is. Some 728 * attributes have multiple equivalent values. 729 */ 730 731 function getValueForAttribute(node, name, expected, isCustomComponentTag) { 732 { 733 if (!isAttributeNameSafe(name)) { 734 return; 735 } 736 737 if (!node.hasAttribute(name)) { 738 return expected === undefined ? undefined : null; 739 } 740 741 var value = node.getAttribute(name); 742 743 { 744 checkAttributeStringCoercion(expected, name); 745 } 746 747 if (value === '' + expected) { 748 return expected; 749 } 750 751 return value; 752 } 753 } 754 /** 755 * Sets the value for a property on a node. 756 * 757 * @param {DOMElement} node 758 * @param {string} name 759 * @param {*} value 760 */ 761 762 function setValueForProperty(node, name, value, isCustomComponentTag) { 763 var propertyInfo = getPropertyInfo(name); 764 765 if (shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag)) { 766 return; 767 } 768 769 if (shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag)) { 770 value = null; 771 } 772 773 774 if (isCustomComponentTag || propertyInfo === null) { 775 if (isAttributeNameSafe(name)) { 776 var _attributeName = name; 777 778 if (value === null) { 779 node.removeAttribute(_attributeName); 780 } else { 781 { 782 checkAttributeStringCoercion(value, name); 783 } 784 785 node.setAttribute(_attributeName, '' + value); 786 } 787 } 788 789 return; 790 } 791 792 var mustUseProperty = propertyInfo.mustUseProperty; 793 794 if (mustUseProperty) { 795 var propertyName = propertyInfo.propertyName; 796 797 if (value === null) { 798 var type = propertyInfo.type; 799 node[propertyName] = type === BOOLEAN ? false : ''; 800 } else { 801 // Contrary to `setAttribute`, object properties are properly 802 // `toString`ed by IE8/9. 803 node[propertyName] = value; 804 } 805 806 return; 807 } // The rest are treated as attributes with special cases. 808 809 810 var attributeName = propertyInfo.attributeName, 811 attributeNamespace = propertyInfo.attributeNamespace; 812 813 if (value === null) { 814 node.removeAttribute(attributeName); 815 } else { 816 var _type = propertyInfo.type; 817 var attributeValue; 818 819 if (_type === BOOLEAN || _type === OVERLOADED_BOOLEAN && value === true) { 820 // If attribute type is boolean, we know for sure it won't be an execution sink 821 // and we won't require Trusted Type here. 822 attributeValue = ''; 823 } else { 824 // `setAttribute` with objects becomes only `[object]` in IE8/9, 825 // ('' + value) makes it output the correct toString()-value. 826 { 827 { 828 checkAttributeStringCoercion(value, attributeName); 829 } 830 831 attributeValue = '' + value; 832 } 833 834 if (propertyInfo.sanitizeURL) { 835 sanitizeURL(attributeValue.toString()); 836 } 837 } 838 839 if (attributeNamespace) { 840 node.setAttributeNS(attributeNamespace, attributeName, attributeValue); 841 } else { 842 node.setAttribute(attributeName, attributeValue); 843 } 844 } 845 } 846 847 // ATTENTION 848 // When adding new symbols to this file, 849 // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' 850 // The Symbol used to tag the ReactElement-like types. 851 var REACT_ELEMENT_TYPE = Symbol.for('react.element'); 852 var REACT_PORTAL_TYPE = Symbol.for('react.portal'); 853 var REACT_FRAGMENT_TYPE = Symbol.for('react.fragment'); 854 var REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode'); 855 var REACT_PROFILER_TYPE = Symbol.for('react.profiler'); 856 var REACT_PROVIDER_TYPE = Symbol.for('react.provider'); 857 var REACT_CONTEXT_TYPE = Symbol.for('react.context'); 858 var REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref'); 859 var REACT_SUSPENSE_TYPE = Symbol.for('react.suspense'); 860 var REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list'); 861 var REACT_MEMO_TYPE = Symbol.for('react.memo'); 862 var REACT_LAZY_TYPE = Symbol.for('react.lazy'); 863 var REACT_SCOPE_TYPE = Symbol.for('react.scope'); 864 var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for('react.debug_trace_mode'); 865 var REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen'); 866 var REACT_LEGACY_HIDDEN_TYPE = Symbol.for('react.legacy_hidden'); 867 var REACT_CACHE_TYPE = Symbol.for('react.cache'); 868 var REACT_TRACING_MARKER_TYPE = Symbol.for('react.tracing_marker'); 869 var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; 870 var FAUX_ITERATOR_SYMBOL = '@@iterator'; 871 function getIteratorFn(maybeIterable) { 872 if (maybeIterable === null || typeof maybeIterable !== 'object') { 873 return null; 874 } 875 876 var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]; 877 878 if (typeof maybeIterator === 'function') { 879 return maybeIterator; 880 } 881 882 return null; 883 } 884 885 var assign = Object.assign; 886 887 // Helpers to patch console.logs to avoid logging during side-effect free 888 // replaying on render function. This currently only patches the object 889 // lazily which won't cover if the log function was extracted eagerly. 890 // We could also eagerly patch the method. 891 var disabledDepth = 0; 892 var prevLog; 893 var prevInfo; 894 var prevWarn; 895 var prevError; 896 var prevGroup; 897 var prevGroupCollapsed; 898 var prevGroupEnd; 899 900 function disabledLog() {} 901 902 disabledLog.__reactDisabledLog = true; 903 function disableLogs() { 904 { 905 if (disabledDepth === 0) { 906 /* eslint-disable react-internal/no-production-logging */ 907 prevLog = console.log; 908 prevInfo = console.info; 909 prevWarn = console.warn; 910 prevError = console.error; 911 prevGroup = console.group; 912 prevGroupCollapsed = console.groupCollapsed; 913 prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 914 915 var props = { 916 configurable: true, 917 enumerable: true, 918 value: disabledLog, 919 writable: true 920 }; // $FlowFixMe Flow thinks console is immutable. 921 922 Object.defineProperties(console, { 923 info: props, 924 log: props, 925 warn: props, 926 error: props, 927 group: props, 928 groupCollapsed: props, 929 groupEnd: props 930 }); 931 /* eslint-enable react-internal/no-production-logging */ 932 } 933 934 disabledDepth++; 935 } 936 } 937 function reenableLogs() { 938 { 939 disabledDepth--; 940 941 if (disabledDepth === 0) { 942 /* eslint-disable react-internal/no-production-logging */ 943 var props = { 944 configurable: true, 945 enumerable: true, 946 writable: true 947 }; // $FlowFixMe Flow thinks console is immutable. 948 949 Object.defineProperties(console, { 950 log: assign({}, props, { 951 value: prevLog 952 }), 953 info: assign({}, props, { 954 value: prevInfo 955 }), 956 warn: assign({}, props, { 957 value: prevWarn 958 }), 959 error: assign({}, props, { 960 value: prevError 961 }), 962 group: assign({}, props, { 963 value: prevGroup 964 }), 965 groupCollapsed: assign({}, props, { 966 value: prevGroupCollapsed 967 }), 968 groupEnd: assign({}, props, { 969 value: prevGroupEnd 970 }) 971 }); 972 /* eslint-enable react-internal/no-production-logging */ 973 } 974 975 if (disabledDepth < 0) { 976 error('disabledDepth fell below zero. ' + 'This is a bug in React. Please file an issue.'); 977 } 978 } 979 } 980 981 var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; 982 var prefix; 983 function describeBuiltInComponentFrame(name, source, ownerFn) { 984 { 985 if (prefix === undefined) { 986 // Extract the VM specific prefix used by each line. 987 try { 988 throw Error(); 989 } catch (x) { 990 var match = x.stack.trim().match(/\n( *(at )?)/); 991 prefix = match && match[1] || ''; 992 } 993 } // We use the prefix to ensure our stacks line up with native stack frames. 994 995 996 return '\n' + prefix + name; 997 } 998 } 999 var reentry = false; 1000 var componentFrameCache; 1001 1002 { 1003 var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map; 1004 componentFrameCache = new PossiblyWeakMap(); 1005 } 1006 1007 function describeNativeComponentFrame(fn, construct) { 1008 // If something asked for a stack inside a fake render, it should get ignored. 1009 if ( !fn || reentry) { 1010 return ''; 1011 } 1012 1013 { 1014 var frame = componentFrameCache.get(fn); 1015 1016 if (frame !== undefined) { 1017 return frame; 1018 } 1019 } 1020 1021 var control; 1022 reentry = true; 1023 var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe It does accept undefined. 1024 1025 Error.prepareStackTrace = undefined; 1026 var previousDispatcher; 1027 1028 { 1029 previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function 1030 // for warnings. 1031 1032 ReactCurrentDispatcher.current = null; 1033 disableLogs(); 1034 } 1035 1036 try { 1037 // This should throw. 1038 if (construct) { 1039 // Something should be setting the props in the constructor. 1040 var Fake = function () { 1041 throw Error(); 1042 }; // $FlowFixMe 1043 1044 1045 Object.defineProperty(Fake.prototype, 'props', { 1046 set: function () { 1047 // We use a throwing setter instead of frozen or non-writable props 1048 // because that won't throw in a non-strict mode function. 1049 throw Error(); 1050 } 1051 }); 1052 1053 if (typeof Reflect === 'object' && Reflect.construct) { 1054 // We construct a different control for this case to include any extra 1055 // frames added by the construct call. 1056 try { 1057 Reflect.construct(Fake, []); 1058 } catch (x) { 1059 control = x; 1060 } 1061 1062 Reflect.construct(fn, [], Fake); 1063 } else { 1064 try { 1065 Fake.call(); 1066 } catch (x) { 1067 control = x; 1068 } 1069 1070 fn.call(Fake.prototype); 1071 } 1072 } else { 1073 try { 1074 throw Error(); 1075 } catch (x) { 1076 control = x; 1077 } 1078 1079 fn(); 1080 } 1081 } catch (sample) { 1082 // This is inlined manually because closure doesn't do it for us. 1083 if (sample && control && typeof sample.stack === 'string') { 1084 // This extracts the first frame from the sample that isn't also in the control. 1085 // Skipping one frame that we assume is the frame that calls the two. 1086 var sampleLines = sample.stack.split('\n'); 1087 var controlLines = control.stack.split('\n'); 1088 var s = sampleLines.length - 1; 1089 var c = controlLines.length - 1; 1090 1091 while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { 1092 // We expect at least one stack frame to be shared. 1093 // Typically this will be the root most one. However, stack frames may be 1094 // cut off due to maximum stack limits. In this case, one maybe cut off 1095 // earlier than the other. We assume that the sample is longer or the same 1096 // and there for cut off earlier. So we should find the root most frame in 1097 // the sample somewhere in the control. 1098 c--; 1099 } 1100 1101 for (; s >= 1 && c >= 0; s--, c--) { 1102 // Next we find the first one that isn't the same which should be the 1103 // frame that called our sample function and the control. 1104 if (sampleLines[s] !== controlLines[c]) { 1105 // In V8, the first line is describing the message but other VMs don't. 1106 // If we're about to return the first line, and the control is also on the same 1107 // line, that's a pretty good indicator that our sample threw at same line as 1108 // the control. I.e. before we entered the sample frame. So we ignore this result. 1109 // This can happen if you passed a class to function component, or non-function. 1110 if (s !== 1 || c !== 1) { 1111 do { 1112 s--; 1113 c--; // We may still have similar intermediate frames from the construct call. 1114 // The next one that isn't the same should be our match though. 1115 1116 if (c < 0 || sampleLines[s] !== controlLines[c]) { 1117 // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. 1118 var _frame = '\n' + sampleLines[s].replace(' at new ', ' at '); // If our component frame is labeled "<anonymous>" 1119 // but we have a user-provided "displayName" 1120 // splice it in to make the stack more readable. 1121 1122 1123 if (fn.displayName && _frame.includes('<anonymous>')) { 1124 _frame = _frame.replace('<anonymous>', fn.displayName); 1125 } 1126 1127 { 1128 if (typeof fn === 'function') { 1129 componentFrameCache.set(fn, _frame); 1130 } 1131 } // Return the line we found. 1132 1133 1134 return _frame; 1135 } 1136 } while (s >= 1 && c >= 0); 1137 } 1138 1139 break; 1140 } 1141 } 1142 } 1143 } finally { 1144 reentry = false; 1145 1146 { 1147 ReactCurrentDispatcher.current = previousDispatcher; 1148 reenableLogs(); 1149 } 1150 1151 Error.prepareStackTrace = previousPrepareStackTrace; 1152 } // Fallback to just using the name if we couldn't make it throw. 1153 1154 1155 var name = fn ? fn.displayName || fn.name : ''; 1156 var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ''; 1157 1158 { 1159 if (typeof fn === 'function') { 1160 componentFrameCache.set(fn, syntheticFrame); 1161 } 1162 } 1163 1164 return syntheticFrame; 1165 } 1166 1167 function describeClassComponentFrame(ctor, source, ownerFn) { 1168 { 1169 return describeNativeComponentFrame(ctor, true); 1170 } 1171 } 1172 function describeFunctionComponentFrame(fn, source, ownerFn) { 1173 { 1174 return describeNativeComponentFrame(fn, false); 1175 } 1176 } 1177 1178 function shouldConstruct(Component) { 1179 var prototype = Component.prototype; 1180 return !!(prototype && prototype.isReactComponent); 1181 } 1182 1183 function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { 1184 1185 if (type == null) { 1186 return ''; 1187 } 1188 1189 if (typeof type === 'function') { 1190 { 1191 return describeNativeComponentFrame(type, shouldConstruct(type)); 1192 } 1193 } 1194 1195 if (typeof type === 'string') { 1196 return describeBuiltInComponentFrame(type); 1197 } 1198 1199 switch (type) { 1200 case REACT_SUSPENSE_TYPE: 1201 return describeBuiltInComponentFrame('Suspense'); 1202 1203 case REACT_SUSPENSE_LIST_TYPE: 1204 return describeBuiltInComponentFrame('SuspenseList'); 1205 } 1206 1207 if (typeof type === 'object') { 1208 switch (type.$$typeof) { 1209 case REACT_FORWARD_REF_TYPE: 1210 return describeFunctionComponentFrame(type.render); 1211 1212 case REACT_MEMO_TYPE: 1213 // Memo may contain any component type so we recursively resolve it. 1214 return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); 1215 1216 case REACT_LAZY_TYPE: 1217 { 1218 var lazyComponent = type; 1219 var payload = lazyComponent._payload; 1220 var init = lazyComponent._init; 1221 1222 try { 1223 // Lazy may contain any component type so we recursively resolve it. 1224 return describeUnknownElementTypeFrameInDEV(init(payload), source, ownerFn); 1225 } catch (x) {} 1226 } 1227 } 1228 } 1229 1230 return ''; 1231 } 1232 1233 function describeFiber(fiber) { 1234 var owner = fiber._debugOwner ? fiber._debugOwner.type : null ; 1235 var source = fiber._debugSource ; 1236 1237 switch (fiber.tag) { 1238 case HostComponent: 1239 return describeBuiltInComponentFrame(fiber.type); 1240 1241 case LazyComponent: 1242 return describeBuiltInComponentFrame('Lazy'); 1243 1244 case SuspenseComponent: 1245 return describeBuiltInComponentFrame('Suspense'); 1246 1247 case SuspenseListComponent: 1248 return describeBuiltInComponentFrame('SuspenseList'); 1249 1250 case FunctionComponent: 1251 case IndeterminateComponent: 1252 case SimpleMemoComponent: 1253 return describeFunctionComponentFrame(fiber.type); 1254 1255 case ForwardRef: 1256 return describeFunctionComponentFrame(fiber.type.render); 1257 1258 case ClassComponent: 1259 return describeClassComponentFrame(fiber.type); 1260 1261 default: 1262 return ''; 1263 } 1264 } 1265 1266 function getStackByFiberInDevAndProd(workInProgress) { 1267 try { 1268 var info = ''; 1269 var node = workInProgress; 1270 1271 do { 1272 info += describeFiber(node); 1273 node = node.return; 1274 } while (node); 1275 1276 return info; 1277 } catch (x) { 1278 return '\nError generating stack: ' + x.message + '\n' + x.stack; 1279 } 1280 } 1281 1282 function getWrappedName(outerType, innerType, wrapperName) { 1283 var displayName = outerType.displayName; 1284 1285 if (displayName) { 1286 return displayName; 1287 } 1288 1289 var functionName = innerType.displayName || innerType.name || ''; 1290 return functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName; 1291 } // Keep in sync with react-reconciler/getComponentNameFromFiber 1292 1293 1294 function getContextName(type) { 1295 return type.displayName || 'Context'; 1296 } // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. 1297 1298 1299 function getComponentNameFromType(type) { 1300 if (type == null) { 1301 // Host root, text node or just invalid type. 1302 return null; 1303 } 1304 1305 { 1306 if (typeof type.tag === 'number') { 1307 error('Received an unexpected object in getComponentNameFromType(). ' + 'This is likely a bug in React. Please file an issue.'); 1308 } 1309 } 1310 1311 if (typeof type === 'function') { 1312 return type.displayName || type.name || null; 1313 } 1314 1315 if (typeof type === 'string') { 1316 return type; 1317 } 1318 1319 switch (type) { 1320 case REACT_FRAGMENT_TYPE: 1321 return 'Fragment'; 1322 1323 case REACT_PORTAL_TYPE: 1324 return 'Portal'; 1325 1326 case REACT_PROFILER_TYPE: 1327 return 'Profiler'; 1328 1329 case REACT_STRICT_MODE_TYPE: 1330 return 'StrictMode'; 1331 1332 case REACT_SUSPENSE_TYPE: 1333 return 'Suspense'; 1334 1335 case REACT_SUSPENSE_LIST_TYPE: 1336 return 'SuspenseList'; 1337 1338 } 1339 1340 if (typeof type === 'object') { 1341 switch (type.$$typeof) { 1342 case REACT_CONTEXT_TYPE: 1343 var context = type; 1344 return getContextName(context) + '.Consumer'; 1345 1346 case REACT_PROVIDER_TYPE: 1347 var provider = type; 1348 return getContextName(provider._context) + '.Provider'; 1349 1350 case REACT_FORWARD_REF_TYPE: 1351 return getWrappedName(type, type.render, 'ForwardRef'); 1352 1353 case REACT_MEMO_TYPE: 1354 var outerName = type.displayName || null; 1355 1356 if (outerName !== null) { 1357 return outerName; 1358 } 1359 1360 return getComponentNameFromType(type.type) || 'Memo'; 1361 1362 case REACT_LAZY_TYPE: 1363 { 1364 var lazyComponent = type; 1365 var payload = lazyComponent._payload; 1366 var init = lazyComponent._init; 1367 1368 try { 1369 return getComponentNameFromType(init(payload)); 1370 } catch (x) { 1371 return null; 1372 } 1373 } 1374 1375 // eslint-disable-next-line no-fallthrough 1376 } 1377 } 1378 1379 return null; 1380 } 1381 1382 function getWrappedName$1(outerType, innerType, wrapperName) { 1383 var functionName = innerType.displayName || innerType.name || ''; 1384 return outerType.displayName || (functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName); 1385 } // Keep in sync with shared/getComponentNameFromType 1386 1387 1388 function getContextName$1(type) { 1389 return type.displayName || 'Context'; 1390 } 1391 1392 function getComponentNameFromFiber(fiber) { 1393 var tag = fiber.tag, 1394 type = fiber.type; 1395 1396 switch (tag) { 1397 case CacheComponent: 1398 return 'Cache'; 1399 1400 case ContextConsumer: 1401 var context = type; 1402 return getContextName$1(context) + '.Consumer'; 1403 1404 case ContextProvider: 1405 var provider = type; 1406 return getContextName$1(provider._context) + '.Provider'; 1407 1408 case DehydratedFragment: 1409 return 'DehydratedFragment'; 1410 1411 case ForwardRef: 1412 return getWrappedName$1(type, type.render, 'ForwardRef'); 1413 1414 case Fragment: 1415 return 'Fragment'; 1416 1417 case HostComponent: 1418 // Host component type is the display name (e.g. "div", "View") 1419 return type; 1420 1421 case HostPortal: 1422 return 'Portal'; 1423 1424 case HostRoot: 1425 return 'Root'; 1426 1427 case HostText: 1428 return 'Text'; 1429 1430 case LazyComponent: 1431 // Name comes from the type in this case; we don't have a tag. 1432 return getComponentNameFromType(type); 1433 1434 case Mode: 1435 if (type === REACT_STRICT_MODE_TYPE) { 1436 // Don't be less specific than shared/getComponentNameFromType 1437 return 'StrictMode'; 1438 } 1439 1440 return 'Mode'; 1441 1442 case OffscreenComponent: 1443 return 'Offscreen'; 1444 1445 case Profiler: 1446 return 'Profiler'; 1447 1448 case ScopeComponent: 1449 return 'Scope'; 1450 1451 case SuspenseComponent: 1452 return 'Suspense'; 1453 1454 case SuspenseListComponent: 1455 return 'SuspenseList'; 1456 1457 case TracingMarkerComponent: 1458 return 'TracingMarker'; 1459 // The display name for this tags come from the user-provided type: 1460 1461 case ClassComponent: 1462 case FunctionComponent: 1463 case IncompleteClassComponent: 1464 case IndeterminateComponent: 1465 case MemoComponent: 1466 case SimpleMemoComponent: 1467 if (typeof type === 'function') { 1468 return type.displayName || type.name || null; 1469 } 1470 1471 if (typeof type === 'string') { 1472 return type; 1473 } 1474 1475 break; 1476 1477 } 1478 1479 return null; 1480 } 1481 1482 var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; 1483 var current = null; 1484 var isRendering = false; 1485 function getCurrentFiberOwnerNameInDevOrNull() { 1486 { 1487 if (current === null) { 1488 return null; 1489 } 1490 1491 var owner = current._debugOwner; 1492 1493 if (owner !== null && typeof owner !== 'undefined') { 1494 return getComponentNameFromFiber(owner); 1495 } 1496 } 1497 1498 return null; 1499 } 1500 1501 function getCurrentFiberStackInDev() { 1502 { 1503 if (current === null) { 1504 return ''; 1505 } // Safe because if current fiber exists, we are reconciling, 1506 // and it is guaranteed to be the work-in-progress version. 1507 1508 1509 return getStackByFiberInDevAndProd(current); 1510 } 1511 } 1512 1513 function resetCurrentFiber() { 1514 { 1515 ReactDebugCurrentFrame.getCurrentStack = null; 1516 current = null; 1517 isRendering = false; 1518 } 1519 } 1520 function setCurrentFiber(fiber) { 1521 { 1522 ReactDebugCurrentFrame.getCurrentStack = fiber === null ? null : getCurrentFiberStackInDev; 1523 current = fiber; 1524 isRendering = false; 1525 } 1526 } 1527 function getCurrentFiber() { 1528 { 1529 return current; 1530 } 1531 } 1532 function setIsRendering(rendering) { 1533 { 1534 isRendering = rendering; 1535 } 1536 } 1537 1538 // Flow does not allow string concatenation of most non-string types. To work 1539 // around this limitation, we use an opaque type that can only be obtained by 1540 // passing the value through getToStringValue first. 1541 function toString(value) { 1542 // The coercion safety check is performed in getToStringValue(). 1543 // eslint-disable-next-line react-internal/safe-string-coercion 1544 return '' + value; 1545 } 1546 function getToStringValue(value) { 1547 switch (typeof value) { 1548 case 'boolean': 1549 case 'number': 1550 case 'string': 1551 case 'undefined': 1552 return value; 1553 1554 case 'object': 1555 { 1556 checkFormFieldValueStringCoercion(value); 1557 } 1558 1559 return value; 1560 1561 default: 1562 // function, symbol are assigned as empty strings 1563 return ''; 1564 } 1565 } 1566 1567 var hasReadOnlyValue = { 1568 button: true, 1569 checkbox: true, 1570 image: true, 1571 hidden: true, 1572 radio: true, 1573 reset: true, 1574 submit: true 1575 }; 1576 function checkControlledValueProps(tagName, props) { 1577 { 1578 if (!(hasReadOnlyValue[props.type] || props.onChange || props.onInput || props.readOnly || props.disabled || props.value == null)) { 1579 error('You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.'); 1580 } 1581 1582 if (!(props.onChange || props.readOnly || props.disabled || props.checked == null)) { 1583 error('You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.'); 1584 } 1585 } 1586 } 1587 1588 function isCheckable(elem) { 1589 var type = elem.type; 1590 var nodeName = elem.nodeName; 1591 return nodeName && nodeName.toLowerCase() === 'input' && (type === 'checkbox' || type === 'radio'); 1592 } 1593 1594 function getTracker(node) { 1595 return node._valueTracker; 1596 } 1597 1598 function detachTracker(node) { 1599 node._valueTracker = null; 1600 } 1601 1602 function getValueFromNode(node) { 1603 var value = ''; 1604 1605 if (!node) { 1606 return value; 1607 } 1608 1609 if (isCheckable(node)) { 1610 value = node.checked ? 'true' : 'false'; 1611 } else { 1612 value = node.value; 1613 } 1614 1615 return value; 1616 } 1617 1618 function trackValueOnNode(node) { 1619 var valueField = isCheckable(node) ? 'checked' : 'value'; 1620 var descriptor = Object.getOwnPropertyDescriptor(node.constructor.prototype, valueField); 1621 1622 { 1623 checkFormFieldValueStringCoercion(node[valueField]); 1624 } 1625 1626 var currentValue = '' + node[valueField]; // if someone has already defined a value or Safari, then bail 1627 // and don't track value will cause over reporting of changes, 1628 // but it's better then a hard failure 1629 // (needed for certain tests that spyOn input values and Safari) 1630 1631 if (node.hasOwnProperty(valueField) || typeof descriptor === 'undefined' || typeof descriptor.get !== 'function' || typeof descriptor.set !== 'function') { 1632 return; 1633 } 1634 1635 var get = descriptor.get, 1636 set = descriptor.set; 1637 Object.defineProperty(node, valueField, { 1638 configurable: true, 1639 get: function () { 1640 return get.call(this); 1641 }, 1642 set: function (value) { 1643 { 1644 checkFormFieldValueStringCoercion(value); 1645 } 1646 1647 currentValue = '' + value; 1648 set.call(this, value); 1649 } 1650 }); // We could've passed this the first time 1651 // but it triggers a bug in IE11 and Edge 14/15. 1652 // Calling defineProperty() again should be equivalent. 1653 // https://github.com/facebook/react/issues/11768 1654 1655 Object.defineProperty(node, valueField, { 1656 enumerable: descriptor.enumerable 1657 }); 1658 var tracker = { 1659 getValue: function () { 1660 return currentValue; 1661 }, 1662 setValue: function (value) { 1663 { 1664 checkFormFieldValueStringCoercion(value); 1665 } 1666 1667 currentValue = '' + value; 1668 }, 1669 stopTracking: function () { 1670 detachTracker(node); 1671 delete node[valueField]; 1672 } 1673 }; 1674 return tracker; 1675 } 1676 1677 function track(node) { 1678 if (getTracker(node)) { 1679 return; 1680 } // TODO: Once it's just Fiber we can move this to node._wrapperState 1681 1682 1683 node._valueTracker = trackValueOnNode(node); 1684 } 1685 function updateValueIfChanged(node) { 1686 if (!node) { 1687 return false; 1688 } 1689 1690 var tracker = getTracker(node); // if there is no tracker at this point it's unlikely 1691 // that trying again will succeed 1692 1693 if (!tracker) { 1694 return true; 1695 } 1696 1697 var lastValue = tracker.getValue(); 1698 var nextValue = getValueFromNode(node); 1699 1700 if (nextValue !== lastValue) { 1701 tracker.setValue(nextValue); 1702 return true; 1703 } 1704 1705 return false; 1706 } 1707 1708 function getActiveElement(doc) { 1709 doc = doc || (typeof document !== 'undefined' ? document : undefined); 1710 1711 if (typeof doc === 'undefined') { 1712 return null; 1713 } 1714 1715 try { 1716 return doc.activeElement || doc.body; 1717 } catch (e) { 1718 return doc.body; 1719 } 1720 } 1721 1722 var didWarnValueDefaultValue = false; 1723 var didWarnCheckedDefaultChecked = false; 1724 var didWarnControlledToUncontrolled = false; 1725 var didWarnUncontrolledToControlled = false; 1726 1727 function isControlled(props) { 1728 var usesChecked = props.type === 'checkbox' || props.type === 'radio'; 1729 return usesChecked ? props.checked != null : props.value != null; 1730 } 1731 /** 1732 * Implements an <input> host component that allows setting these optional 1733 * props: `checked`, `value`, `defaultChecked`, and `defaultValue`. 1734 * 1735 * If `checked` or `value` are not supplied (or null/undefined), user actions 1736 * that affect the checked state or value will trigger updates to the element. 1737 * 1738 * If they are supplied (and not null/undefined), the rendered element will not 1739 * trigger updates to the element. Instead, the props must change in order for 1740 * the rendered element to be updated. 1741 * 1742 * The rendered element will be initialized as unchecked (or `defaultChecked`) 1743 * with an empty value (or `defaultValue`). 1744 * 1745 * See http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html 1746 */ 1747 1748 1749 function getHostProps(element, props) { 1750 var node = element; 1751 var checked = props.checked; 1752 var hostProps = assign({}, props, { 1753 defaultChecked: undefined, 1754 defaultValue: undefined, 1755 value: undefined, 1756 checked: checked != null ? checked : node._wrapperState.initialChecked 1757 }); 1758 return hostProps; 1759 } 1760 function initWrapperState(element, props) { 1761 { 1762 checkControlledValueProps('input', props); 1763 1764 if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) { 1765 error('%s contains an input of type %s with both checked and defaultChecked props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://reactjs.org/link/controlled-components', getCurrentFiberOwnerNameInDevOrNull() || 'A component', props.type); 1766 1767 didWarnCheckedDefaultChecked = true; 1768 } 1769 1770 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) { 1771 error('%s contains an input of type %s with both value and defaultValue props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://reactjs.org/link/controlled-components', getCurrentFiberOwnerNameInDevOrNull() || 'A component', props.type); 1772 1773 didWarnValueDefaultValue = true; 1774 } 1775 } 1776 1777 var node = element; 1778 var defaultValue = props.defaultValue == null ? '' : props.defaultValue; 1779 node._wrapperState = { 1780 initialChecked: props.checked != null ? props.checked : props.defaultChecked, 1781 initialValue: getToStringValue(props.value != null ? props.value : defaultValue), 1782 controlled: isControlled(props) 1783 }; 1784 } 1785 function updateChecked(element, props) { 1786 var node = element; 1787 var checked = props.checked; 1788 1789 if (checked != null) { 1790 setValueForProperty(node, 'checked', checked, false); 1791 } 1792 } 1793 function updateWrapper(element, props) { 1794 var node = element; 1795 1796 { 1797 var controlled = isControlled(props); 1798 1799 if (!node._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) { 1800 error('A component is changing an uncontrolled input to be controlled. ' + 'This is likely caused by the value changing from undefined to ' + 'a defined value, which should not happen. ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components'); 1801 1802 didWarnUncontrolledToControlled = true; 1803 } 1804 1805 if (node._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) { 1806 error('A component is changing a controlled input to be uncontrolled. ' + 'This is likely caused by the value changing from a defined to ' + 'undefined, which should not happen. ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components'); 1807 1808 didWarnControlledToUncontrolled = true; 1809 } 1810 } 1811 1812 updateChecked(element, props); 1813 var value = getToStringValue(props.value); 1814 var type = props.type; 1815 1816 if (value != null) { 1817 if (type === 'number') { 1818 if (value === 0 && node.value === '' || // We explicitly want to coerce to number here if possible. 1819 // eslint-disable-next-line 1820 node.value != value) { 1821 node.value = toString(value); 1822 } 1823 } else if (node.value !== toString(value)) { 1824 node.value = toString(value); 1825 } 1826 } else if (type === 'submit' || type === 'reset') { 1827 // Submit/reset inputs need the attribute removed completely to avoid 1828 // blank-text buttons. 1829 node.removeAttribute('value'); 1830 return; 1831 } 1832 1833 { 1834 // When syncing the value attribute, the value comes from a cascade of 1835 // properties: 1836 // 1. The value React property 1837 // 2. The defaultValue React property 1838 // 3. Otherwise there should be no change 1839 if (props.hasOwnProperty('value')) { 1840 setDefaultValue(node, props.type, value); 1841 } else if (props.hasOwnProperty('defaultValue')) { 1842 setDefaultValue(node, props.type, getToStringValue(props.defaultValue)); 1843 } 1844 } 1845 1846 { 1847 // When syncing the checked attribute, it only changes when it needs 1848 // to be removed, such as transitioning from a checkbox into a text input 1849 if (props.checked == null && props.defaultChecked != null) { 1850 node.defaultChecked = !!props.defaultChecked; 1851 } 1852 } 1853 } 1854 function postMountWrapper(element, props, isHydrating) { 1855 var node = element; // Do not assign value if it is already set. This prevents user text input 1856 // from being lost during SSR hydration. 1857 1858 if (props.hasOwnProperty('value') || props.hasOwnProperty('defaultValue')) { 1859 var type = props.type; 1860 var isButton = type === 'submit' || type === 'reset'; // Avoid setting value attribute on submit/reset inputs as it overrides the 1861 // default value provided by the browser. See: #12872 1862 1863 if (isButton && (props.value === undefined || props.value === null)) { 1864 return; 1865 } 1866 1867 var initialValue = toString(node._wrapperState.initialValue); // Do not assign value if it is already set. This prevents user text input 1868 // from being lost during SSR hydration. 1869 1870 if (!isHydrating) { 1871 { 1872 // When syncing the value attribute, the value property should use 1873 // the wrapperState._initialValue property. This uses: 1874 // 1875 // 1. The value React property when present 1876 // 2. The defaultValue React property when present 1877 // 3. An empty string 1878 if (initialValue !== node.value) { 1879 node.value = initialValue; 1880 } 1881 } 1882 } 1883 1884 { 1885 // Otherwise, the value attribute is synchronized to the property, 1886 // so we assign defaultValue to the same thing as the value property 1887 // assignment step above. 1888 node.defaultValue = initialValue; 1889 } 1890 } // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug 1891 // this is needed to work around a chrome bug where setting defaultChecked 1892 // will sometimes influence the value of checked (even after detachment). 1893 // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416 1894 // We need to temporarily unset name to avoid disrupting radio button groups. 1895 1896 1897 var name = node.name; 1898 1899 if (name !== '') { 1900 node.name = ''; 1901 } 1902 1903 { 1904 // When syncing the checked attribute, both the checked property and 1905 // attribute are assigned at the same time using defaultChecked. This uses: 1906 // 1907 // 1. The checked React property when present 1908 // 2. The defaultChecked React property when present 1909 // 3. Otherwise, false 1910 node.defaultChecked = !node.defaultChecked; 1911 node.defaultChecked = !!node._wrapperState.initialChecked; 1912 } 1913 1914 if (name !== '') { 1915 node.name = name; 1916 } 1917 } 1918 function restoreControlledState(element, props) { 1919 var node = element; 1920 updateWrapper(node, props); 1921 updateNamedCousins(node, props); 1922 } 1923 1924 function updateNamedCousins(rootNode, props) { 1925 var name = props.name; 1926 1927 if (props.type === 'radio' && name != null) { 1928 var queryRoot = rootNode; 1929 1930 while (queryRoot.parentNode) { 1931 queryRoot = queryRoot.parentNode; 1932 } // If `rootNode.form` was non-null, then we could try `form.elements`, 1933 // but that sometimes behaves strangely in IE8. We could also try using 1934 // `form.getElementsByName`, but that will only return direct children 1935 // and won't include inputs that use the HTML5 `form=` attribute. Since 1936 // the input might not even be in a form. It might not even be in the 1937 // document. Let's just use the local `querySelectorAll` to ensure we don't 1938 // miss anything. 1939 1940 1941 { 1942 checkAttributeStringCoercion(name, 'name'); 1943 } 1944 1945 var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type="radio"]'); 1946 1947 for (var i = 0; i < group.length; i++) { 1948 var otherNode = group[i]; 1949 1950 if (otherNode === rootNode || otherNode.form !== rootNode.form) { 1951 continue; 1952 } // This will throw if radio buttons rendered by different copies of React 1953 // and the same name are rendered into the same form (same as #1939). 1954 // That's probably okay; we don't support it just as we don't support 1955 // mixing React radio buttons with non-React ones. 1956 1957 1958 var otherProps = getFiberCurrentPropsFromNode(otherNode); 1959 1960 if (!otherProps) { 1961 throw new Error('ReactDOMInput: Mixing React and non-React radio inputs with the ' + 'same `name` is not supported.'); 1962 } // We need update the tracked value on the named cousin since the value 1963 // was changed but the input saw no event or value set 1964 1965 1966 updateValueIfChanged(otherNode); // If this is a controlled radio button group, forcing the input that 1967 // was previously checked to update will cause it to be come re-checked 1968 // as appropriate. 1969 1970 updateWrapper(otherNode, otherProps); 1971 } 1972 } 1973 } // In Chrome, assigning defaultValue to certain input types triggers input validation. 1974 // For number inputs, the display value loses trailing decimal points. For email inputs, 1975 // Chrome raises "The specified value <x> is not a valid email address". 1976 // 1977 // Here we check to see if the defaultValue has actually changed, avoiding these problems 1978 // when the user is inputting text 1979 // 1980 // https://github.com/facebook/react/issues/7253 1981 1982 1983 function setDefaultValue(node, type, value) { 1984 if ( // Focused number inputs synchronize on blur. See ChangeEventPlugin.js 1985 type !== 'number' || getActiveElement(node.ownerDocument) !== node) { 1986 if (value == null) { 1987 node.defaultValue = toString(node._wrapperState.initialValue); 1988 } else if (node.defaultValue !== toString(value)) { 1989 node.defaultValue = toString(value); 1990 } 1991 } 1992 } 1993 1994 var didWarnSelectedSetOnOption = false; 1995 var didWarnInvalidChild = false; 1996 var didWarnInvalidInnerHTML = false; 1997 /** 1998 * Implements an <option> host component that warns when `selected` is set. 1999 */ 2000 2001 function validateProps(element, props) { 2002 { 2003 // If a value is not provided, then the children must be simple. 2004 if (props.value == null) { 2005 if (typeof props.children === 'object' && props.children !== null) { 2006 React.Children.forEach(props.children, function (child) { 2007 if (child == null) { 2008 return; 2009 } 2010 2011 if (typeof child === 'string' || typeof child === 'number') { 2012 return; 2013 } 2014 2015 if (!didWarnInvalidChild) { 2016 didWarnInvalidChild = true; 2017 2018 error('Cannot infer the option value of complex children. ' + 'Pass a `value` prop or use a plain string as children to <option>.'); 2019 } 2020 }); 2021 } else if (props.dangerouslySetInnerHTML != null) { 2022 if (!didWarnInvalidInnerHTML) { 2023 didWarnInvalidInnerHTML = true; 2024 2025 error('Pass a `value` prop if you set dangerouslyInnerHTML so React knows ' + 'which value should be selected.'); 2026 } 2027 } 2028 } // TODO: Remove support for `selected` in <option>. 2029 2030 2031 if (props.selected != null && !didWarnSelectedSetOnOption) { 2032 error('Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.'); 2033 2034 didWarnSelectedSetOnOption = true; 2035 } 2036 } 2037 } 2038 function postMountWrapper$1(element, props) { 2039 // value="" should make a value attribute (#6219) 2040 if (props.value != null) { 2041 element.setAttribute('value', toString(getToStringValue(props.value))); 2042 } 2043 } 2044 2045 var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare 2046 2047 function isArray(a) { 2048 return isArrayImpl(a); 2049 } 2050 2051 var didWarnValueDefaultValue$1; 2052 2053 { 2054 didWarnValueDefaultValue$1 = false; 2055 } 2056 2057 function getDeclarationErrorAddendum() { 2058 var ownerName = getCurrentFiberOwnerNameInDevOrNull(); 2059 2060 if (ownerName) { 2061 return '\n\nCheck the render method of `' + ownerName + '`.'; 2062 } 2063 2064 return ''; 2065 } 2066 2067 var valuePropNames = ['value', 'defaultValue']; 2068 /** 2069 * Validation function for `value` and `defaultValue`. 2070 */ 2071 2072 function checkSelectPropTypes(props) { 2073 { 2074 checkControlledValueProps('select', props); 2075 2076 for (var i = 0; i < valuePropNames.length; i++) { 2077 var propName = valuePropNames[i]; 2078 2079 if (props[propName] == null) { 2080 continue; 2081 } 2082 2083 var propNameIsArray = isArray(props[propName]); 2084 2085 if (props.multiple && !propNameIsArray) { 2086 error('The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum()); 2087 } else if (!props.multiple && propNameIsArray) { 2088 error('The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum()); 2089 } 2090 } 2091 } 2092 } 2093 2094 function updateOptions(node, multiple, propValue, setDefaultSelected) { 2095 var options = node.options; 2096 2097 if (multiple) { 2098 var selectedValues = propValue; 2099 var selectedValue = {}; 2100 2101 for (var i = 0; i < selectedValues.length; i++) { 2102 // Prefix to avoid chaos with special keys. 2103 selectedValue['$' + selectedValues[i]] = true; 2104 } 2105 2106 for (var _i = 0; _i < options.length; _i++) { 2107 var selected = selectedValue.hasOwnProperty('$' + options[_i].value); 2108 2109 if (options[_i].selected !== selected) { 2110 options[_i].selected = selected; 2111 } 2112 2113 if (selected && setDefaultSelected) { 2114 options[_i].defaultSelected = true; 2115 } 2116 } 2117 } else { 2118 // Do not set `select.value` as exact behavior isn't consistent across all 2119 // browsers for all cases. 2120 var _selectedValue = toString(getToStringValue(propValue)); 2121 2122 var defaultSelected = null; 2123 2124 for (var _i2 = 0; _i2 < options.length; _i2++) { 2125 if (options[_i2].value === _selectedValue) { 2126 options[_i2].selected = true; 2127 2128 if (setDefaultSelected) { 2129 options[_i2].defaultSelected = true; 2130 } 2131 2132 return; 2133 } 2134 2135 if (defaultSelected === null && !options[_i2].disabled) { 2136 defaultSelected = options[_i2]; 2137 } 2138 } 2139 2140 if (defaultSelected !== null) { 2141 defaultSelected.selected = true; 2142 } 2143 } 2144 } 2145 /** 2146 * Implements a <select> host component that allows optionally setting the 2147 * props `value` and `defaultValue`. If `multiple` is false, the prop must be a 2148 * stringable. If `multiple` is true, the prop must be an array of stringables. 2149 * 2150 * If `value` is not supplied (or null/undefined), user actions that change the 2151 * selected option will trigger updates to the rendered options. 2152 * 2153 * If it is supplied (and not null/undefined), the rendered options will not 2154 * update in response to user actions. Instead, the `value` prop must change in 2155 * order for the rendered options to update. 2156 * 2157 * If `defaultValue` is provided, any options with the supplied values will be 2158 * selected. 2159 */ 2160 2161 2162 function getHostProps$1(element, props) { 2163 return assign({}, props, { 2164 value: undefined 2165 }); 2166 } 2167 function initWrapperState$1(element, props) { 2168 var node = element; 2169 2170 { 2171 checkSelectPropTypes(props); 2172 } 2173 2174 node._wrapperState = { 2175 wasMultiple: !!props.multiple 2176 }; 2177 2178 { 2179 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue$1) { 2180 error('Select elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled select ' + 'element and remove one of these props. More info: ' + 'https://reactjs.org/link/controlled-components'); 2181 2182 didWarnValueDefaultValue$1 = true; 2183 } 2184 } 2185 } 2186 function postMountWrapper$2(element, props) { 2187 var node = element; 2188 node.multiple = !!props.multiple; 2189 var value = props.value; 2190 2191 if (value != null) { 2192 updateOptions(node, !!props.multiple, value, false); 2193 } else if (props.defaultValue != null) { 2194 updateOptions(node, !!props.multiple, props.defaultValue, true); 2195 } 2196 } 2197 function postUpdateWrapper(element, props) { 2198 var node = element; 2199 var wasMultiple = node._wrapperState.wasMultiple; 2200 node._wrapperState.wasMultiple = !!props.multiple; 2201 var value = props.value; 2202 2203 if (value != null) { 2204 updateOptions(node, !!props.multiple, value, false); 2205 } else if (wasMultiple !== !!props.multiple) { 2206 // For simplicity, reapply `defaultValue` if `multiple` is toggled. 2207 if (props.defaultValue != null) { 2208 updateOptions(node, !!props.multiple, props.defaultValue, true); 2209 } else { 2210 // Revert the select back to its default unselected state. 2211 updateOptions(node, !!props.multiple, props.multiple ? [] : '', false); 2212 } 2213 } 2214 } 2215 function restoreControlledState$1(element, props) { 2216 var node = element; 2217 var value = props.value; 2218 2219 if (value != null) { 2220 updateOptions(node, !!props.multiple, value, false); 2221 } 2222 } 2223 2224 var didWarnValDefaultVal = false; 2225 2226 /** 2227 * Implements a <textarea> host component that allows setting `value`, and 2228 * `defaultValue`. This differs from the traditional DOM API because value is 2229 * usually set as PCDATA children. 2230 * 2231 * If `value` is not supplied (or null/undefined), user actions that affect the 2232 * value will trigger updates to the element. 2233 * 2234 * If `value` is supplied (and not null/undefined), the rendered element will 2235 * not trigger updates to the element. Instead, the `value` prop must change in 2236 * order for the rendered element to be updated. 2237 * 2238 * The rendered element will be initialized with an empty value, the prop 2239 * `defaultValue` if specified, or the children content (deprecated). 2240 */ 2241 function getHostProps$2(element, props) { 2242 var node = element; 2243 2244 if (props.dangerouslySetInnerHTML != null) { 2245 throw new Error('`dangerouslySetInnerHTML` does not make sense on <textarea>.'); 2246 } // Always set children to the same thing. In IE9, the selection range will 2247 // get reset if `textContent` is mutated. We could add a check in setTextContent 2248 // to only set the value if/when the value differs from the node value (which would 2249 // completely solve this IE9 bug), but Sebastian+Sophie seemed to like this 2250 // solution. The value can be a boolean or object so that's why it's forced 2251 // to be a string. 2252 2253 2254 var hostProps = assign({}, props, { 2255 value: undefined, 2256 defaultValue: undefined, 2257 children: toString(node._wrapperState.initialValue) 2258 }); 2259 2260 return hostProps; 2261 } 2262 function initWrapperState$2(element, props) { 2263 var node = element; 2264 2265 { 2266 checkControlledValueProps('textarea', props); 2267 2268 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) { 2269 error('%s contains a textarea with both value and defaultValue props. ' + 'Textarea elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled textarea ' + 'and remove one of these props. More info: ' + 'https://reactjs.org/link/controlled-components', getCurrentFiberOwnerNameInDevOrNull() || 'A component'); 2270 2271 didWarnValDefaultVal = true; 2272 } 2273 } 2274 2275 var initialValue = props.value; // Only bother fetching default value if we're going to use it 2276 2277 if (initialValue == null) { 2278 var children = props.children, 2279 defaultValue = props.defaultValue; 2280 2281 if (children != null) { 2282 { 2283 error('Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.'); 2284 } 2285 2286 { 2287 if (defaultValue != null) { 2288 throw new Error('If you supply `defaultValue` on a <textarea>, do not pass children.'); 2289 } 2290 2291 if (isArray(children)) { 2292 if (children.length > 1) { 2293 throw new Error('<textarea> can only have at most one child.'); 2294 } 2295 2296 children = children[0]; 2297 } 2298 2299 defaultValue = children; 2300 } 2301 } 2302 2303 if (defaultValue == null) { 2304 defaultValue = ''; 2305 } 2306 2307 initialValue = defaultValue; 2308 } 2309 2310 node._wrapperState = { 2311 initialValue: getToStringValue(initialValue) 2312 }; 2313 } 2314 function updateWrapper$1(element, props) { 2315 var node = element; 2316 var value = getToStringValue(props.value); 2317 var defaultValue = getToStringValue(props.defaultValue); 2318 2319 if (value != null) { 2320 // Cast `value` to a string to ensure the value is set correctly. While 2321 // browsers typically do this as necessary, jsdom doesn't. 2322 var newValue = toString(value); // To avoid side effects (such as losing text selection), only set value if changed 2323 2324 if (newValue !== node.value) { 2325 node.value = newValue; 2326 } 2327 2328 if (props.defaultValue == null && node.defaultValue !== newValue) { 2329 node.defaultValue = newValue; 2330 } 2331 } 2332 2333 if (defaultValue != null) { 2334 node.defaultValue = toString(defaultValue); 2335 } 2336 } 2337 function postMountWrapper$3(element, props) { 2338 var node = element; // This is in postMount because we need access to the DOM node, which is not 2339 // available until after the component has mounted. 2340 2341 var textContent = node.textContent; // Only set node.value if textContent is equal to the expected 2342 // initial value. In IE10/IE11 there is a bug where the placeholder attribute 2343 // will populate textContent as well. 2344 // https://developer.microsoft.com/microsoft-edge/platform/issues/101525/ 2345 2346 if (textContent === node._wrapperState.initialValue) { 2347 if (textContent !== '' && textContent !== null) { 2348 node.value = textContent; 2349 } 2350 } 2351 } 2352 function restoreControlledState$2(element, props) { 2353 // DOM component is still mounted; update 2354 updateWrapper$1(element, props); 2355 } 2356 2357 var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml'; 2358 var MATH_NAMESPACE = 'http://www.w3.org/1998/Math/MathML'; 2359 var SVG_NAMESPACE = 'http://www.w3.org/2000/svg'; // Assumes there is no parent namespace. 2360 2361 function getIntrinsicNamespace(type) { 2362 switch (type) { 2363 case 'svg': 2364 return SVG_NAMESPACE; 2365 2366 case 'math': 2367 return MATH_NAMESPACE; 2368 2369 default: 2370 return HTML_NAMESPACE; 2371 } 2372 } 2373 function getChildNamespace(parentNamespace, type) { 2374 if (parentNamespace == null || parentNamespace === HTML_NAMESPACE) { 2375 // No (or default) parent namespace: potential entry point. 2376 return getIntrinsicNamespace(type); 2377 } 2378 2379 if (parentNamespace === SVG_NAMESPACE && type === 'foreignObject') { 2380 // We're leaving SVG. 2381 return HTML_NAMESPACE; 2382 } // By default, pass namespace below. 2383 2384 2385 return parentNamespace; 2386 } 2387 2388 /* globals MSApp */ 2389 2390 /** 2391 * Create a function which has 'unsafe' privileges (required by windows8 apps) 2392 */ 2393 var createMicrosoftUnsafeLocalFunction = function (func) { 2394 if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) { 2395 return function (arg0, arg1, arg2, arg3) { 2396 MSApp.execUnsafeLocalFunction(function () { 2397 return func(arg0, arg1, arg2, arg3); 2398 }); 2399 }; 2400 } else { 2401 return func; 2402 } 2403 }; 2404 2405 var reusableSVGContainer; 2406 /** 2407 * Set the innerHTML property of a node 2408 * 2409 * @param {DOMElement} node 2410 * @param {string} html 2411 * @internal 2412 */ 2413 2414 var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) { 2415 if (node.namespaceURI === SVG_NAMESPACE) { 2416 2417 if (!('innerHTML' in node)) { 2418 // IE does not have innerHTML for SVG nodes, so instead we inject the 2419 // new markup in a temp node and then move the child nodes across into 2420 // the target node 2421 reusableSVGContainer = reusableSVGContainer || document.createElement('div'); 2422 reusableSVGContainer.innerHTML = '<svg>' + html.valueOf().toString() + '</svg>'; 2423 var svgNode = reusableSVGContainer.firstChild; 2424 2425 while (node.firstChild) { 2426 node.removeChild(node.firstChild); 2427 } 2428 2429 while (svgNode.firstChild) { 2430 node.appendChild(svgNode.firstChild); 2431 } 2432 2433 return; 2434 } 2435 } 2436 2437 node.innerHTML = html; 2438 }); 2439 2440 /** 2441 * HTML nodeType values that represent the type of the node 2442 */ 2443 var ELEMENT_NODE = 1; 2444 var TEXT_NODE = 3; 2445 var COMMENT_NODE = 8; 2446 var DOCUMENT_NODE = 9; 2447 var DOCUMENT_FRAGMENT_NODE = 11; 2448 2449 /** 2450 * Set the textContent property of a node. For text updates, it's faster 2451 * to set the `nodeValue` of the Text node directly instead of using 2452 * `.textContent` which will remove the existing node and create a new one. 2453 * 2454 * @param {DOMElement} node 2455 * @param {string} text 2456 * @internal 2457 */ 2458 2459 var setTextContent = function (node, text) { 2460 if (text) { 2461 var firstChild = node.firstChild; 2462 2463 if (firstChild && firstChild === node.lastChild && firstChild.nodeType === TEXT_NODE) { 2464 firstChild.nodeValue = text; 2465 return; 2466 } 2467 } 2468 2469 node.textContent = text; 2470 }; 2471 2472 // List derived from Gecko source code: 2473 // https://github.com/mozilla/gecko-dev/blob/4e638efc71/layout/style/test/property_database.js 2474 var shorthandToLonghand = { 2475 animation: ['animationDelay', 'animationDirection', 'animationDuration', 'animationFillMode', 'animationIterationCount', 'animationName', 'animationPlayState', 'animationTimingFunction'], 2476 background: ['backgroundAttachment', 'backgroundClip', 'backgroundColor', 'backgroundImage', 'backgroundOrigin', 'backgroundPositionX', 'backgroundPositionY', 'backgroundRepeat', 'backgroundSize'], 2477 backgroundPosition: ['backgroundPositionX', 'backgroundPositionY'], 2478 border: ['borderBottomColor', 'borderBottomStyle', 'borderBottomWidth', 'borderImageOutset', 'borderImageRepeat', 'borderImageSlice', 'borderImageSource', 'borderImageWidth', 'borderLeftColor', 'borderLeftStyle', 'borderLeftWidth', 'borderRightColor', 'borderRightStyle', 'borderRightWidth', 'borderTopColor', 'borderTopStyle', 'borderTopWidth'], 2479 borderBlockEnd: ['borderBlockEndColor', 'borderBlockEndStyle', 'borderBlockEndWidth'], 2480 borderBlockStart: ['borderBlockStartColor', 'borderBlockStartStyle', 'borderBlockStartWidth'], 2481 borderBottom: ['borderBottomColor', 'borderBottomStyle', 'borderBottomWidth'], 2482 borderColor: ['borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor'], 2483 borderImage: ['borderImageOutset', 'borderImageRepeat', 'borderImageSlice', 'borderImageSource', 'borderImageWidth'], 2484 borderInlineEnd: ['borderInlineEndColor', 'borderInlineEndStyle', 'borderInlineEndWidth'], 2485 borderInlineStart: ['borderInlineStartColor', 'borderInlineStartStyle', 'borderInlineStartWidth'], 2486 borderLeft: ['borderLeftColor', 'borderLeftStyle', 'borderLeftWidth'], 2487 borderRadius: ['borderBottomLeftRadius', 'borderBottomRightRadius', 'borderTopLeftRadius', 'borderTopRightRadius'], 2488 borderRight: ['borderRightColor', 'borderRightStyle', 'borderRightWidth'], 2489 borderStyle: ['borderBottomStyle', 'borderLeftStyle', 'borderRightStyle', 'borderTopStyle'], 2490 borderTop: ['borderTopColor', 'borderTopStyle', 'borderTopWidth'], 2491 borderWidth: ['borderBottomWidth', 'borderLeftWidth', 'borderRightWidth', 'borderTopWidth'], 2492 columnRule: ['columnRuleColor', 'columnRuleStyle', 'columnRuleWidth'], 2493 columns: ['columnCount', 'columnWidth'], 2494 flex: ['flexBasis', 'flexGrow', 'flexShrink'], 2495 flexFlow: ['flexDirection', 'flexWrap'], 2496 font: ['fontFamily', 'fontFeatureSettings', 'fontKerning', 'fontLanguageOverride', 'fontSize', 'fontSizeAdjust', 'fontStretch', 'fontStyle', 'fontVariant', 'fontVariantAlternates', 'fontVariantCaps', 'fontVariantEastAsian', 'fontVariantLigatures', 'fontVariantNumeric', 'fontVariantPosition', 'fontWeight', 'lineHeight'], 2497 fontVariant: ['fontVariantAlternates', 'fontVariantCaps', 'fontVariantEastAsian', 'fontVariantLigatures', 'fontVariantNumeric', 'fontVariantPosition'], 2498 gap: ['columnGap', 'rowGap'], 2499 grid: ['gridAutoColumns', 'gridAutoFlow', 'gridAutoRows', 'gridTemplateAreas', 'gridTemplateColumns', 'gridTemplateRows'], 2500 gridArea: ['gridColumnEnd', 'gridColumnStart', 'gridRowEnd', 'gridRowStart'], 2501 gridColumn: ['gridColumnEnd', 'gridColumnStart'], 2502 gridColumnGap: ['columnGap'], 2503 gridGap: ['columnGap', 'rowGap'], 2504 gridRow: ['gridRowEnd', 'gridRowStart'], 2505 gridRowGap: ['rowGap'], 2506 gridTemplate: ['gridTemplateAreas', 'gridTemplateColumns', 'gridTemplateRows'], 2507 listStyle: ['listStyleImage', 'listStylePosition', 'listStyleType'], 2508 margin: ['marginBottom', 'marginLeft', 'marginRight', 'marginTop'], 2509 marker: ['markerEnd', 'markerMid', 'markerStart'], 2510 mask: ['maskClip', 'maskComposite', 'maskImage', 'maskMode', 'maskOrigin', 'maskPositionX', 'maskPositionY', 'maskRepeat', 'maskSize'], 2511 maskPosition: ['maskPositionX', 'maskPositionY'], 2512 outline: ['outlineColor', 'outlineStyle', 'outlineWidth'], 2513 overflow: ['overflowX', 'overflowY'], 2514 padding: ['paddingBottom', 'paddingLeft', 'paddingRight', 'paddingTop'], 2515 placeContent: ['alignContent', 'justifyContent'], 2516 placeItems: ['alignItems', 'justifyItems'], 2517 placeSelf: ['alignSelf', 'justifySelf'], 2518 textDecoration: ['textDecorationColor', 'textDecorationLine', 'textDecorationStyle'], 2519 textEmphasis: ['textEmphasisColor', 'textEmphasisStyle'], 2520 transition: ['transitionDelay', 'transitionDuration', 'transitionProperty', 'transitionTimingFunction'], 2521 wordWrap: ['overflowWrap'] 2522 }; 2523 2524 /** 2525 * CSS properties which accept numbers but are not in units of "px". 2526 */ 2527 var isUnitlessNumber = { 2528 animationIterationCount: true, 2529 aspectRatio: true, 2530 borderImageOutset: true, 2531 borderImageSlice: true, 2532 borderImageWidth: true, 2533 boxFlex: true, 2534 boxFlexGroup: true, 2535 boxOrdinalGroup: true, 2536 columnCount: true, 2537 columns: true, 2538 flex: true, 2539 flexGrow: true, 2540 flexPositive: true, 2541 flexShrink: true, 2542 flexNegative: true, 2543 flexOrder: true, 2544 gridArea: true, 2545 gridRow: true, 2546 gridRowEnd: true, 2547 gridRowSpan: true, 2548 gridRowStart: true, 2549 gridColumn: true, 2550 gridColumnEnd: true, 2551 gridColumnSpan: true, 2552 gridColumnStart: true, 2553 fontWeight: true, 2554 lineClamp: true, 2555 lineHeight: true, 2556 opacity: true, 2557 order: true, 2558 orphans: true, 2559 tabSize: true, 2560 widows: true, 2561 zIndex: true, 2562 zoom: true, 2563 // SVG-related properties 2564 fillOpacity: true, 2565 floodOpacity: true, 2566 stopOpacity: true, 2567 strokeDasharray: true, 2568 strokeDashoffset: true, 2569 strokeMiterlimit: true, 2570 strokeOpacity: true, 2571 strokeWidth: true 2572 }; 2573 /** 2574 * @param {string} prefix vendor-specific prefix, eg: Webkit 2575 * @param {string} key style name, eg: transitionDuration 2576 * @return {string} style name prefixed with `prefix`, properly camelCased, eg: 2577 * WebkitTransitionDuration 2578 */ 2579 2580 function prefixKey(prefix, key) { 2581 return prefix + key.charAt(0).toUpperCase() + key.substring(1); 2582 } 2583 /** 2584 * Support style names that may come passed in prefixed by adding permutations 2585 * of vendor prefixes. 2586 */ 2587 2588 2589 var prefixes = ['Webkit', 'ms', 'Moz', 'O']; // Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an 2590 // infinite loop, because it iterates over the newly added props too. 2591 2592 Object.keys(isUnitlessNumber).forEach(function (prop) { 2593 prefixes.forEach(function (prefix) { 2594 isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop]; 2595 }); 2596 }); 2597 2598 /** 2599 * Convert a value into the proper css writable value. The style name `name` 2600 * should be logical (no hyphens), as specified 2601 * in `CSSProperty.isUnitlessNumber`. 2602 * 2603 * @param {string} name CSS property name such as `topMargin`. 2604 * @param {*} value CSS property value such as `10px`. 2605 * @return {string} Normalized style value with dimensions applied. 2606 */ 2607 2608 function dangerousStyleValue(name, value, isCustomProperty) { 2609 // Note that we've removed escapeTextForBrowser() calls here since the 2610 // whole string will be escaped when the attribute is injected into 2611 // the markup. If you provide unsafe user data here they can inject 2612 // arbitrary CSS which may be problematic (I couldn't repro this): 2613 // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet 2614 // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/ 2615 // This is not an XSS hole but instead a potential CSS injection issue 2616 // which has lead to a greater discussion about how we're going to 2617 // trust URLs moving forward. See #2115901 2618 var isEmpty = value == null || typeof value === 'boolean' || value === ''; 2619 2620 if (isEmpty) { 2621 return ''; 2622 } 2623 2624 if (!isCustomProperty && typeof value === 'number' && value !== 0 && !(isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name])) { 2625 return value + 'px'; // Presumes implicit 'px' suffix for unitless numbers 2626 } 2627 2628 { 2629 checkCSSPropertyStringCoercion(value, name); 2630 } 2631 2632 return ('' + value).trim(); 2633 } 2634 2635 var uppercasePattern = /([A-Z])/g; 2636 var msPattern = /^ms-/; 2637 /** 2638 * Hyphenates a camelcased CSS property name, for example: 2639 * 2640 * > hyphenateStyleName('backgroundColor') 2641 * < "background-color" 2642 * > hyphenateStyleName('MozTransition') 2643 * < "-moz-transition" 2644 * > hyphenateStyleName('msTransition') 2645 * < "-ms-transition" 2646 * 2647 * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix 2648 * is converted to `-ms-`. 2649 */ 2650 2651 function hyphenateStyleName(name) { 2652 return name.replace(uppercasePattern, '-$1').toLowerCase().replace(msPattern, '-ms-'); 2653 } 2654 2655 var warnValidStyle = function () {}; 2656 2657 { 2658 // 'msTransform' is correct, but the other prefixes should be capitalized 2659 var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/; 2660 var msPattern$1 = /^-ms-/; 2661 var hyphenPattern = /-(.)/g; // style values shouldn't contain a semicolon 2662 2663 var badStyleValueWithSemicolonPattern = /;\s*$/; 2664 var warnedStyleNames = {}; 2665 var warnedStyleValues = {}; 2666 var warnedForNaNValue = false; 2667 var warnedForInfinityValue = false; 2668 2669 var camelize = function (string) { 2670 return string.replace(hyphenPattern, function (_, character) { 2671 return character.toUpperCase(); 2672 }); 2673 }; 2674 2675 var warnHyphenatedStyleName = function (name) { 2676 if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { 2677 return; 2678 } 2679 2680 warnedStyleNames[name] = true; 2681 2682 error('Unsupported style property %s. Did you mean %s?', name, // As Andi Smith suggests 2683 // (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix 2684 // is converted to lowercase `ms`. 2685 camelize(name.replace(msPattern$1, 'ms-'))); 2686 }; 2687 2688 var warnBadVendoredStyleName = function (name) { 2689 if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { 2690 return; 2691 } 2692 2693 warnedStyleNames[name] = true; 2694 2695 error('Unsupported vendor-prefixed style property %s. Did you mean %s?', name, name.charAt(0).toUpperCase() + name.slice(1)); 2696 }; 2697 2698 var warnStyleValueWithSemicolon = function (name, value) { 2699 if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) { 2700 return; 2701 } 2702 2703 warnedStyleValues[value] = true; 2704 2705 error("Style property values shouldn't contain a semicolon. " + 'Try "%s: %s" instead.', name, value.replace(badStyleValueWithSemicolonPattern, '')); 2706 }; 2707 2708 var warnStyleValueIsNaN = function (name, value) { 2709 if (warnedForNaNValue) { 2710 return; 2711 } 2712 2713 warnedForNaNValue = true; 2714 2715 error('`NaN` is an invalid value for the `%s` css style property.', name); 2716 }; 2717 2718 var warnStyleValueIsInfinity = function (name, value) { 2719 if (warnedForInfinityValue) { 2720 return; 2721 } 2722 2723 warnedForInfinityValue = true; 2724 2725 error('`Infinity` is an invalid value for the `%s` css style property.', name); 2726 }; 2727 2728 warnValidStyle = function (name, value) { 2729 if (name.indexOf('-') > -1) { 2730 warnHyphenatedStyleName(name); 2731 } else if (badVendoredStyleNamePattern.test(name)) { 2732 warnBadVendoredStyleName(name); 2733 } else if (badStyleValueWithSemicolonPattern.test(value)) { 2734 warnStyleValueWithSemicolon(name, value); 2735 } 2736 2737 if (typeof value === 'number') { 2738 if (isNaN(value)) { 2739 warnStyleValueIsNaN(name, value); 2740 } else if (!isFinite(value)) { 2741 warnStyleValueIsInfinity(name, value); 2742 } 2743 } 2744 }; 2745 } 2746 2747 var warnValidStyle$1 = warnValidStyle; 2748 2749 /** 2750 * Operations for dealing with CSS properties. 2751 */ 2752 2753 /** 2754 * This creates a string that is expected to be equivalent to the style 2755 * attribute generated by server-side rendering. It by-passes warnings and 2756 * security checks so it's not safe to use this value for anything other than 2757 * comparison. It is only used in DEV for SSR validation. 2758 */ 2759 2760 function createDangerousStringForStyles(styles) { 2761 { 2762 var serialized = ''; 2763 var delimiter = ''; 2764 2765 for (var styleName in styles) { 2766 if (!styles.hasOwnProperty(styleName)) { 2767 continue; 2768 } 2769 2770 var styleValue = styles[styleName]; 2771 2772 if (styleValue != null) { 2773 var isCustomProperty = styleName.indexOf('--') === 0; 2774 serialized += delimiter + (isCustomProperty ? styleName : hyphenateStyleName(styleName)) + ':'; 2775 serialized += dangerousStyleValue(styleName, styleValue, isCustomProperty); 2776 delimiter = ';'; 2777 } 2778 } 2779 2780 return serialized || null; 2781 } 2782 } 2783 /** 2784 * Sets the value for multiple styles on a node. If a value is specified as 2785 * '' (empty string), the corresponding style property will be unset. 2786 * 2787 * @param {DOMElement} node 2788 * @param {object} styles 2789 */ 2790 2791 function setValueForStyles(node, styles) { 2792 var style = node.style; 2793 2794 for (var styleName in styles) { 2795 if (!styles.hasOwnProperty(styleName)) { 2796 continue; 2797 } 2798 2799 var isCustomProperty = styleName.indexOf('--') === 0; 2800 2801 { 2802 if (!isCustomProperty) { 2803 warnValidStyle$1(styleName, styles[styleName]); 2804 } 2805 } 2806 2807 var styleValue = dangerousStyleValue(styleName, styles[styleName], isCustomProperty); 2808 2809 if (styleName === 'float') { 2810 styleName = 'cssFloat'; 2811 } 2812 2813 if (isCustomProperty) { 2814 style.setProperty(styleName, styleValue); 2815 } else { 2816 style[styleName] = styleValue; 2817 } 2818 } 2819 } 2820 2821 function isValueEmpty(value) { 2822 return value == null || typeof value === 'boolean' || value === ''; 2823 } 2824 /** 2825 * Given {color: 'red', overflow: 'hidden'} returns { 2826 * color: 'color', 2827 * overflowX: 'overflow', 2828 * overflowY: 'overflow', 2829 * }. This can be read as "the overflowY property was set by the overflow 2830 * shorthand". That is, the values are the property that each was derived from. 2831 */ 2832 2833 2834 function expandShorthandMap(styles) { 2835 var expanded = {}; 2836 2837 for (var key in styles) { 2838 var longhands = shorthandToLonghand[key] || [key]; 2839 2840 for (var i = 0; i < longhands.length; i++) { 2841 expanded[longhands[i]] = key; 2842 } 2843 } 2844 2845 return expanded; 2846 } 2847 /** 2848 * When mixing shorthand and longhand property names, we warn during updates if 2849 * we expect an incorrect result to occur. In particular, we warn for: 2850 * 2851 * Updating a shorthand property (longhand gets overwritten): 2852 * {font: 'foo', fontVariant: 'bar'} -> {font: 'baz', fontVariant: 'bar'} 2853 * becomes .style.font = 'baz' 2854 * Removing a shorthand property (longhand gets lost too): 2855 * {font: 'foo', fontVariant: 'bar'} -> {fontVariant: 'bar'} 2856 * becomes .style.font = '' 2857 * Removing a longhand property (should revert to shorthand; doesn't): 2858 * {font: 'foo', fontVariant: 'bar'} -> {font: 'foo'} 2859 * becomes .style.fontVariant = '' 2860 */ 2861 2862 2863 function validateShorthandPropertyCollisionInDev(styleUpdates, nextStyles) { 2864 { 2865 if (!nextStyles) { 2866 return; 2867 } 2868 2869 var expandedUpdates = expandShorthandMap(styleUpdates); 2870 var expandedStyles = expandShorthandMap(nextStyles); 2871 var warnedAbout = {}; 2872 2873 for (var key in expandedUpdates) { 2874 var originalKey = expandedUpdates[key]; 2875 var correctOriginalKey = expandedStyles[key]; 2876 2877 if (correctOriginalKey && originalKey !== correctOriginalKey) { 2878 var warningKey = originalKey + ',' + correctOriginalKey; 2879 2880 if (warnedAbout[warningKey]) { 2881 continue; 2882 } 2883 2884 warnedAbout[warningKey] = true; 2885 2886 error('%s a style property during rerender (%s) when a ' + 'conflicting property is set (%s) can lead to styling bugs. To ' + "avoid this, don't mix shorthand and non-shorthand properties " + 'for the same value; instead, replace the shorthand with ' + 'separate values.', isValueEmpty(styleUpdates[originalKey]) ? 'Removing' : 'Updating', originalKey, correctOriginalKey); 2887 } 2888 } 2889 } 2890 } 2891 2892 // For HTML, certain tags should omit their close tag. We keep a list for 2893 // those special-case tags. 2894 var omittedCloseTags = { 2895 area: true, 2896 base: true, 2897 br: true, 2898 col: true, 2899 embed: true, 2900 hr: true, 2901 img: true, 2902 input: true, 2903 keygen: true, 2904 link: true, 2905 meta: true, 2906 param: true, 2907 source: true, 2908 track: true, 2909 wbr: true // NOTE: menuitem's close tag should be omitted, but that causes problems. 2910 2911 }; 2912 2913 // `omittedCloseTags` except that `menuitem` should still have its closing tag. 2914 2915 var voidElementTags = assign({ 2916 menuitem: true 2917 }, omittedCloseTags); 2918 2919 var HTML = '__html'; 2920 2921 function assertValidProps(tag, props) { 2922 if (!props) { 2923 return; 2924 } // Note the use of `==` which checks for null or undefined. 2925 2926 2927 if (voidElementTags[tag]) { 2928 if (props.children != null || props.dangerouslySetInnerHTML != null) { 2929 throw new Error(tag + " is a void element tag and must neither have `children` nor " + 'use `dangerouslySetInnerHTML`.'); 2930 } 2931 } 2932 2933 if (props.dangerouslySetInnerHTML != null) { 2934 if (props.children != null) { 2935 throw new Error('Can only set one of `children` or `props.dangerouslySetInnerHTML`.'); 2936 } 2937 2938 if (typeof props.dangerouslySetInnerHTML !== 'object' || !(HTML in props.dangerouslySetInnerHTML)) { 2939 throw new Error('`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + 'Please visit https://reactjs.org/link/dangerously-set-inner-html ' + 'for more information.'); 2940 } 2941 } 2942 2943 { 2944 if (!props.suppressContentEditableWarning && props.contentEditable && props.children != null) { 2945 error('A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.'); 2946 } 2947 } 2948 2949 if (props.style != null && typeof props.style !== 'object') { 2950 throw new Error('The `style` prop expects a mapping from style properties to values, ' + "not a string. For example, style={{marginRight: spacing + 'em'}} when " + 'using JSX.'); 2951 } 2952 } 2953 2954 function isCustomComponent(tagName, props) { 2955 if (tagName.indexOf('-') === -1) { 2956 return typeof props.is === 'string'; 2957 } 2958 2959 switch (tagName) { 2960 // These are reserved SVG and MathML elements. 2961 // We don't mind this list too much because we expect it to never grow. 2962 // The alternative is to track the namespace in a few places which is convoluted. 2963 // https://w3c.github.io/webcomponents/spec/custom/#custom-elements-core-concepts 2964 case 'annotation-xml': 2965 case 'color-profile': 2966 case 'font-face': 2967 case 'font-face-src': 2968 case 'font-face-uri': 2969 case 'font-face-format': 2970 case 'font-face-name': 2971 case 'missing-glyph': 2972 return false; 2973 2974 default: 2975 return true; 2976 } 2977 } 2978 2979 // When adding attributes to the HTML or SVG allowed attribute list, be sure to 2980 // also add them to this module to ensure casing and incorrect name 2981 // warnings. 2982 var possibleStandardNames = { 2983 // HTML 2984 accept: 'accept', 2985 acceptcharset: 'acceptCharset', 2986 'accept-charset': 'acceptCharset', 2987 accesskey: 'accessKey', 2988 action: 'action', 2989 allowfullscreen: 'allowFullScreen', 2990 alt: 'alt', 2991 as: 'as', 2992 async: 'async', 2993 autocapitalize: 'autoCapitalize', 2994 autocomplete: 'autoComplete', 2995 autocorrect: 'autoCorrect', 2996 autofocus: 'autoFocus', 2997 autoplay: 'autoPlay', 2998 autosave: 'autoSave', 2999 capture: 'capture', 3000 cellpadding: 'cellPadding', 3001 cellspacing: 'cellSpacing', 3002 challenge: 'challenge', 3003 charset: 'charSet', 3004 checked: 'checked', 3005 children: 'children', 3006 cite: 'cite', 3007 class: 'className', 3008 classid: 'classID', 3009 classname: 'className', 3010 cols: 'cols', 3011 colspan: 'colSpan', 3012 content: 'content', 3013 contenteditable: 'contentEditable', 3014 contextmenu: 'contextMenu', 3015 controls: 'controls', 3016 controlslist: 'controlsList', 3017 coords: 'coords', 3018 crossorigin: 'crossOrigin', 3019 dangerouslysetinnerhtml: 'dangerouslySetInnerHTML', 3020 data: 'data', 3021 datetime: 'dateTime', 3022 default: 'default', 3023 defaultchecked: 'defaultChecked', 3024 defaultvalue: 'defaultValue', 3025 defer: 'defer', 3026 dir: 'dir', 3027 disabled: 'disabled', 3028 disablepictureinpicture: 'disablePictureInPicture', 3029 disableremoteplayback: 'disableRemotePlayback', 3030 download: 'download', 3031 draggable: 'draggable', 3032 enctype: 'encType', 3033 enterkeyhint: 'enterKeyHint', 3034 for: 'htmlFor', 3035 form: 'form', 3036 formmethod: 'formMethod', 3037 formaction: 'formAction', 3038 formenctype: 'formEncType', 3039 formnovalidate: 'formNoValidate', 3040 formtarget: 'formTarget', 3041 frameborder: 'frameBorder', 3042 headers: 'headers', 3043 height: 'height', 3044 hidden: 'hidden', 3045 high: 'high', 3046 href: 'href', 3047 hreflang: 'hrefLang', 3048 htmlfor: 'htmlFor', 3049 httpequiv: 'httpEquiv', 3050 'http-equiv': 'httpEquiv', 3051 icon: 'icon', 3052 id: 'id', 3053 imagesizes: 'imageSizes', 3054 imagesrcset: 'imageSrcSet', 3055 innerhtml: 'innerHTML', 3056 inputmode: 'inputMode', 3057 integrity: 'integrity', 3058 is: 'is', 3059 itemid: 'itemID', 3060 itemprop: 'itemProp', 3061 itemref: 'itemRef', 3062 itemscope: 'itemScope', 3063 itemtype: 'itemType', 3064 keyparams: 'keyParams', 3065 keytype: 'keyType', 3066 kind: 'kind', 3067 label: 'label', 3068 lang: 'lang', 3069 list: 'list', 3070 loop: 'loop', 3071 low: 'low', 3072 manifest: 'manifest', 3073 marginwidth: 'marginWidth', 3074 marginheight: 'marginHeight', 3075 max: 'max', 3076 maxlength: 'maxLength', 3077 media: 'media', 3078 mediagroup: 'mediaGroup', 3079 method: 'method', 3080 min: 'min', 3081 minlength: 'minLength', 3082 multiple: 'multiple', 3083 muted: 'muted', 3084 name: 'name', 3085 nomodule: 'noModule', 3086 nonce: 'nonce', 3087 novalidate: 'noValidate', 3088 open: 'open', 3089 optimum: 'optimum', 3090 pattern: 'pattern', 3091 placeholder: 'placeholder', 3092 playsinline: 'playsInline', 3093 poster: 'poster', 3094 preload: 'preload', 3095 profile: 'profile', 3096 radiogroup: 'radioGroup', 3097 readonly: 'readOnly', 3098 referrerpolicy: 'referrerPolicy', 3099 rel: 'rel', 3100 required: 'required', 3101 reversed: 'reversed', 3102 role: 'role', 3103 rows: 'rows', 3104 rowspan: 'rowSpan', 3105 sandbox: 'sandbox', 3106 scope: 'scope', 3107 scoped: 'scoped', 3108 scrolling: 'scrolling', 3109 seamless: 'seamless', 3110 selected: 'selected', 3111 shape: 'shape', 3112 size: 'size', 3113 sizes: 'sizes', 3114 span: 'span', 3115 spellcheck: 'spellCheck', 3116 src: 'src', 3117 srcdoc: 'srcDoc', 3118 srclang: 'srcLang', 3119 srcset: 'srcSet', 3120 start: 'start', 3121 step: 'step', 3122 style: 'style', 3123 summary: 'summary', 3124 tabindex: 'tabIndex', 3125 target: 'target', 3126 title: 'title', 3127 type: 'type', 3128 usemap: 'useMap', 3129 value: 'value', 3130 width: 'width', 3131 wmode: 'wmode', 3132 wrap: 'wrap', 3133 // SVG 3134 about: 'about', 3135 accentheight: 'accentHeight', 3136 'accent-height': 'accentHeight', 3137 accumulate: 'accumulate', 3138 additive: 'additive', 3139 alignmentbaseline: 'alignmentBaseline', 3140 'alignment-baseline': 'alignmentBaseline', 3141 allowreorder: 'allowReorder', 3142 alphabetic: 'alphabetic', 3143 amplitude: 'amplitude', 3144 arabicform: 'arabicForm', 3145 'arabic-form': 'arabicForm', 3146 ascent: 'ascent', 3147 attributename: 'attributeName', 3148 attributetype: 'attributeType', 3149 autoreverse: 'autoReverse', 3150 azimuth: 'azimuth', 3151 basefrequency: 'baseFrequency', 3152 baselineshift: 'baselineShift', 3153 'baseline-shift': 'baselineShift', 3154 baseprofile: 'baseProfile', 3155 bbox: 'bbox', 3156 begin: 'begin', 3157 bias: 'bias', 3158 by: 'by', 3159 calcmode: 'calcMode', 3160 capheight: 'capHeight', 3161 'cap-height': 'capHeight', 3162 clip: 'clip', 3163 clippath: 'clipPath', 3164 'clip-path': 'clipPath', 3165 clippathunits: 'clipPathUnits', 3166 cliprule: 'clipRule', 3167 'clip-rule': 'clipRule', 3168 color: 'color', 3169 colorinterpolation: 'colorInterpolation', 3170 'color-interpolation': 'colorInterpolation', 3171 colorinterpolationfilters: 'colorInterpolationFilters', 3172 'color-interpolation-filters': 'colorInterpolationFilters', 3173 colorprofile: 'colorProfile', 3174 'color-profile': 'colorProfile', 3175 colorrendering: 'colorRendering', 3176 'color-rendering': 'colorRendering', 3177 contentscripttype: 'contentScriptType', 3178 contentstyletype: 'contentStyleType', 3179 cursor: 'cursor', 3180 cx: 'cx', 3181 cy: 'cy', 3182 d: 'd', 3183 datatype: 'datatype', 3184 decelerate: 'decelerate', 3185 descent: 'descent', 3186 diffuseconstant: 'diffuseConstant', 3187 direction: 'direction', 3188 display: 'display', 3189 divisor: 'divisor', 3190 dominantbaseline: 'dominantBaseline', 3191 'dominant-baseline': 'dominantBaseline', 3192 dur: 'dur', 3193 dx: 'dx', 3194 dy: 'dy', 3195 edgemode: 'edgeMode', 3196 elevation: 'elevation', 3197 enablebackground: 'enableBackground', 3198 'enable-background': 'enableBackground', 3199 end: 'end', 3200 exponent: 'exponent', 3201 externalresourcesrequired: 'externalResourcesRequired', 3202 fill: 'fill', 3203 fillopacity: 'fillOpacity', 3204 'fill-opacity': 'fillOpacity', 3205 fillrule: 'fillRule', 3206 'fill-rule': 'fillRule', 3207 filter: 'filter', 3208 filterres: 'filterRes', 3209 filterunits: 'filterUnits', 3210 floodopacity: 'floodOpacity', 3211 'flood-opacity': 'floodOpacity', 3212 floodcolor: 'floodColor', 3213 'flood-color': 'floodColor', 3214 focusable: 'focusable', 3215 fontfamily: 'fontFamily', 3216 'font-family': 'fontFamily', 3217 fontsize: 'fontSize', 3218 'font-size': 'fontSize', 3219 fontsizeadjust: 'fontSizeAdjust', 3220 'font-size-adjust': 'fontSizeAdjust', 3221 fontstretch: 'fontStretch', 3222 'font-stretch': 'fontStretch', 3223 fontstyle: 'fontStyle', 3224 'font-style': 'fontStyle', 3225 fontvariant: 'fontVariant', 3226 'font-variant': 'fontVariant', 3227 fontweight: 'fontWeight', 3228 'font-weight': 'fontWeight', 3229 format: 'format', 3230 from: 'from', 3231 fx: 'fx', 3232 fy: 'fy', 3233 g1: 'g1', 3234 g2: 'g2', 3235 glyphname: 'glyphName', 3236 'glyph-name': 'glyphName', 3237 glyphorientationhorizontal: 'glyphOrientationHorizontal', 3238 'glyph-orientation-horizontal': 'glyphOrientationHorizontal', 3239 glyphorientationvertical: 'glyphOrientationVertical', 3240 'glyph-orientation-vertical': 'glyphOrientationVertical', 3241 glyphref: 'glyphRef', 3242 gradienttransform: 'gradientTransform', 3243 gradientunits: 'gradientUnits', 3244 hanging: 'hanging', 3245 horizadvx: 'horizAdvX', 3246 'horiz-adv-x': 'horizAdvX', 3247 horizoriginx: 'horizOriginX', 3248 'horiz-origin-x': 'horizOriginX', 3249 ideographic: 'ideographic', 3250 imagerendering: 'imageRendering', 3251 'image-rendering': 'imageRendering', 3252 in2: 'in2', 3253 in: 'in', 3254 inlist: 'inlist', 3255 intercept: 'intercept', 3256 k1: 'k1', 3257 k2: 'k2', 3258 k3: 'k3', 3259 k4: 'k4', 3260 k: 'k', 3261 kernelmatrix: 'kernelMatrix', 3262 kernelunitlength: 'kernelUnitLength', 3263 kerning: 'kerning', 3264 keypoints: 'keyPoints', 3265 keysplines: 'keySplines', 3266 keytimes: 'keyTimes', 3267 lengthadjust: 'lengthAdjust', 3268 letterspacing: 'letterSpacing', 3269 'letter-spacing': 'letterSpacing', 3270 lightingcolor: 'lightingColor', 3271 'lighting-color': 'lightingColor', 3272 limitingconeangle: 'limitingConeAngle', 3273 local: 'local', 3274 markerend: 'markerEnd', 3275 'marker-end': 'markerEnd', 3276 markerheight: 'markerHeight', 3277 markermid: 'markerMid', 3278 'marker-mid': 'markerMid', 3279 markerstart: 'markerStart', 3280 'marker-start': 'markerStart', 3281 markerunits: 'markerUnits', 3282 markerwidth: 'markerWidth', 3283 mask: 'mask', 3284 maskcontentunits: 'maskContentUnits', 3285 maskunits: 'maskUnits', 3286 mathematical: 'mathematical', 3287 mode: 'mode', 3288 numoctaves: 'numOctaves', 3289 offset: 'offset', 3290 opacity: 'opacity', 3291 operator: 'operator', 3292 order: 'order', 3293 orient: 'orient', 3294 orientation: 'orientation', 3295 origin: 'origin', 3296 overflow: 'overflow', 3297 overlineposition: 'overlinePosition', 3298 'overline-position': 'overlinePosition', 3299 overlinethickness: 'overlineThickness', 3300 'overline-thickness': 'overlineThickness', 3301 paintorder: 'paintOrder', 3302 'paint-order': 'paintOrder', 3303 panose1: 'panose1', 3304 'panose-1': 'panose1', 3305 pathlength: 'pathLength', 3306 patterncontentunits: 'patternContentUnits', 3307 patterntransform: 'patternTransform', 3308 patternunits: 'patternUnits', 3309 pointerevents: 'pointerEvents', 3310 'pointer-events': 'pointerEvents', 3311 points: 'points', 3312 pointsatx: 'pointsAtX', 3313 pointsaty: 'pointsAtY', 3314 pointsatz: 'pointsAtZ', 3315 prefix: 'prefix', 3316 preservealpha: 'preserveAlpha', 3317 preserveaspectratio: 'preserveAspectRatio', 3318 primitiveunits: 'primitiveUnits', 3319 property: 'property', 3320 r: 'r', 3321 radius: 'radius', 3322 refx: 'refX', 3323 refy: 'refY', 3324 renderingintent: 'renderingIntent', 3325 'rendering-intent': 'renderingIntent', 3326 repeatcount: 'repeatCount', 3327 repeatdur: 'repeatDur', 3328 requiredextensions: 'requiredExtensions', 3329 requiredfeatures: 'requiredFeatures', 3330 resource: 'resource', 3331 restart: 'restart', 3332 result: 'result', 3333 results: 'results', 3334 rotate: 'rotate', 3335 rx: 'rx', 3336 ry: 'ry', 3337 scale: 'scale', 3338 security: 'security', 3339 seed: 'seed', 3340 shaperendering: 'shapeRendering', 3341 'shape-rendering': 'shapeRendering', 3342 slope: 'slope', 3343 spacing: 'spacing', 3344 specularconstant: 'specularConstant', 3345 specularexponent: 'specularExponent', 3346 speed: 'speed', 3347 spreadmethod: 'spreadMethod', 3348 startoffset: 'startOffset', 3349 stddeviation: 'stdDeviation', 3350 stemh: 'stemh', 3351 stemv: 'stemv', 3352 stitchtiles: 'stitchTiles', 3353 stopcolor: 'stopColor', 3354 'stop-color': 'stopColor', 3355 stopopacity: 'stopOpacity', 3356 'stop-opacity': 'stopOpacity', 3357 strikethroughposition: 'strikethroughPosition', 3358 'strikethrough-position': 'strikethroughPosition', 3359 strikethroughthickness: 'strikethroughThickness', 3360 'strikethrough-thickness': 'strikethroughThickness', 3361 string: 'string', 3362 stroke: 'stroke', 3363 strokedasharray: 'strokeDasharray', 3364 'stroke-dasharray': 'strokeDasharray', 3365 strokedashoffset: 'strokeDashoffset', 3366 'stroke-dashoffset': 'strokeDashoffset', 3367 strokelinecap: 'strokeLinecap', 3368 'stroke-linecap': 'strokeLinecap', 3369 strokelinejoin: 'strokeLinejoin', 3370 'stroke-linejoin': 'strokeLinejoin', 3371 strokemiterlimit: 'strokeMiterlimit', 3372 'stroke-miterlimit': 'strokeMiterlimit', 3373 strokewidth: 'strokeWidth', 3374 'stroke-width': 'strokeWidth', 3375 strokeopacity: 'strokeOpacity', 3376 'stroke-opacity': 'strokeOpacity', 3377 suppresscontenteditablewarning: 'suppressContentEditableWarning', 3378 suppresshydrationwarning: 'suppressHydrationWarning', 3379 surfacescale: 'surfaceScale', 3380 systemlanguage: 'systemLanguage', 3381 tablevalues: 'tableValues', 3382 targetx: 'targetX', 3383 targety: 'targetY', 3384 textanchor: 'textAnchor', 3385 'text-anchor': 'textAnchor', 3386 textdecoration: 'textDecoration', 3387 'text-decoration': 'textDecoration', 3388 textlength: 'textLength', 3389 textrendering: 'textRendering', 3390 'text-rendering': 'textRendering', 3391 to: 'to', 3392 transform: 'transform', 3393 typeof: 'typeof', 3394 u1: 'u1', 3395 u2: 'u2', 3396 underlineposition: 'underlinePosition', 3397 'underline-position': 'underlinePosition', 3398 underlinethickness: 'underlineThickness', 3399 'underline-thickness': 'underlineThickness', 3400 unicode: 'unicode', 3401 unicodebidi: 'unicodeBidi', 3402 'unicode-bidi': 'unicodeBidi', 3403 unicoderange: 'unicodeRange', 3404 'unicode-range': 'unicodeRange', 3405 unitsperem: 'unitsPerEm', 3406 'units-per-em': 'unitsPerEm', 3407 unselectable: 'unselectable', 3408 valphabetic: 'vAlphabetic', 3409 'v-alphabetic': 'vAlphabetic', 3410 values: 'values', 3411 vectoreffect: 'vectorEffect', 3412 'vector-effect': 'vectorEffect', 3413 version: 'version', 3414 vertadvy: 'vertAdvY', 3415 'vert-adv-y': 'vertAdvY', 3416 vertoriginx: 'vertOriginX', 3417 'vert-origin-x': 'vertOriginX', 3418 vertoriginy: 'vertOriginY', 3419 'vert-origin-y': 'vertOriginY', 3420 vhanging: 'vHanging', 3421 'v-hanging': 'vHanging', 3422 videographic: 'vIdeographic', 3423 'v-ideographic': 'vIdeographic', 3424 viewbox: 'viewBox', 3425 viewtarget: 'viewTarget', 3426 visibility: 'visibility', 3427 vmathematical: 'vMathematical', 3428 'v-mathematical': 'vMathematical', 3429 vocab: 'vocab', 3430 widths: 'widths', 3431 wordspacing: 'wordSpacing', 3432 'word-spacing': 'wordSpacing', 3433 writingmode: 'writingMode', 3434 'writing-mode': 'writingMode', 3435 x1: 'x1', 3436 x2: 'x2', 3437 x: 'x', 3438 xchannelselector: 'xChannelSelector', 3439 xheight: 'xHeight', 3440 'x-height': 'xHeight', 3441 xlinkactuate: 'xlinkActuate', 3442 'xlink:actuate': 'xlinkActuate', 3443 xlinkarcrole: 'xlinkArcrole', 3444 'xlink:arcrole': 'xlinkArcrole', 3445 xlinkhref: 'xlinkHref', 3446 'xlink:href': 'xlinkHref', 3447 xlinkrole: 'xlinkRole', 3448 'xlink:role': 'xlinkRole', 3449 xlinkshow: 'xlinkShow', 3450 'xlink:show': 'xlinkShow', 3451 xlinktitle: 'xlinkTitle', 3452 'xlink:title': 'xlinkTitle', 3453 xlinktype: 'xlinkType', 3454 'xlink:type': 'xlinkType', 3455 xmlbase: 'xmlBase', 3456 'xml:base': 'xmlBase', 3457 xmllang: 'xmlLang', 3458 'xml:lang': 'xmlLang', 3459 xmlns: 'xmlns', 3460 'xml:space': 'xmlSpace', 3461 xmlnsxlink: 'xmlnsXlink', 3462 'xmlns:xlink': 'xmlnsXlink', 3463 xmlspace: 'xmlSpace', 3464 y1: 'y1', 3465 y2: 'y2', 3466 y: 'y', 3467 ychannelselector: 'yChannelSelector', 3468 z: 'z', 3469 zoomandpan: 'zoomAndPan' 3470 }; 3471 3472 var ariaProperties = { 3473 'aria-current': 0, 3474 // state 3475 'aria-description': 0, 3476 'aria-details': 0, 3477 'aria-disabled': 0, 3478 // state 3479 'aria-hidden': 0, 3480 // state 3481 'aria-invalid': 0, 3482 // state 3483 'aria-keyshortcuts': 0, 3484 'aria-label': 0, 3485 'aria-roledescription': 0, 3486 // Widget Attributes 3487 'aria-autocomplete': 0, 3488 'aria-checked': 0, 3489 'aria-expanded': 0, 3490 'aria-haspopup': 0, 3491 'aria-level': 0, 3492 'aria-modal': 0, 3493 'aria-multiline': 0, 3494 'aria-multiselectable': 0, 3495 'aria-orientation': 0, 3496 'aria-placeholder': 0, 3497 'aria-pressed': 0, 3498 'aria-readonly': 0, 3499 'aria-required': 0, 3500 'aria-selected': 0, 3501 'aria-sort': 0, 3502 'aria-valuemax': 0, 3503 'aria-valuemin': 0, 3504 'aria-valuenow': 0, 3505 'aria-valuetext': 0, 3506 // Live Region Attributes 3507 'aria-atomic': 0, 3508 'aria-busy': 0, 3509 'aria-live': 0, 3510 'aria-relevant': 0, 3511 // Drag-and-Drop Attributes 3512 'aria-dropeffect': 0, 3513 'aria-grabbed': 0, 3514 // Relationship Attributes 3515 'aria-activedescendant': 0, 3516 'aria-colcount': 0, 3517 'aria-colindex': 0, 3518 'aria-colspan': 0, 3519 'aria-controls': 0, 3520 'aria-describedby': 0, 3521 'aria-errormessage': 0, 3522 'aria-flowto': 0, 3523 'aria-labelledby': 0, 3524 'aria-owns': 0, 3525 'aria-posinset': 0, 3526 'aria-rowcount': 0, 3527 'aria-rowindex': 0, 3528 'aria-rowspan': 0, 3529 'aria-setsize': 0 3530 }; 3531 3532 var warnedProperties = {}; 3533 var rARIA = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$'); 3534 var rARIACamel = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$'); 3535 3536 function validateProperty(tagName, name) { 3537 { 3538 if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) { 3539 return true; 3540 } 3541 3542 if (rARIACamel.test(name)) { 3543 var ariaName = 'aria-' + name.slice(4).toLowerCase(); 3544 var correctName = ariaProperties.hasOwnProperty(ariaName) ? ariaName : null; // If this is an aria-* attribute, but is not listed in the known DOM 3545 // DOM properties, then it is an invalid aria-* attribute. 3546 3547 if (correctName == null) { 3548 error('Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.', name); 3549 3550 warnedProperties[name] = true; 3551 return true; 3552 } // aria-* attributes should be lowercase; suggest the lowercase version. 3553 3554 3555 if (name !== correctName) { 3556 error('Invalid ARIA attribute `%s`. Did you mean `%s`?', name, correctName); 3557 3558 warnedProperties[name] = true; 3559 return true; 3560 } 3561 } 3562 3563 if (rARIA.test(name)) { 3564 var lowerCasedName = name.toLowerCase(); 3565 var standardName = ariaProperties.hasOwnProperty(lowerCasedName) ? lowerCasedName : null; // If this is an aria-* attribute, but is not listed in the known DOM 3566 // DOM properties, then it is an invalid aria-* attribute. 3567 3568 if (standardName == null) { 3569 warnedProperties[name] = true; 3570 return false; 3571 } // aria-* attributes should be lowercase; suggest the lowercase version. 3572 3573 3574 if (name !== standardName) { 3575 error('Unknown ARIA attribute `%s`. Did you mean `%s`?', name, standardName); 3576 3577 warnedProperties[name] = true; 3578 return true; 3579 } 3580 } 3581 } 3582 3583 return true; 3584 } 3585 3586 function warnInvalidARIAProps(type, props) { 3587 { 3588 var invalidProps = []; 3589 3590 for (var key in props) { 3591 var isValid = validateProperty(type, key); 3592 3593 if (!isValid) { 3594 invalidProps.push(key); 3595 } 3596 } 3597 3598 var unknownPropString = invalidProps.map(function (prop) { 3599 return '`' + prop + '`'; 3600 }).join(', '); 3601 3602 if (invalidProps.length === 1) { 3603 error('Invalid aria prop %s on <%s> tag. ' + 'For details, see https://reactjs.org/link/invalid-aria-props', unknownPropString, type); 3604 } else if (invalidProps.length > 1) { 3605 error('Invalid aria props %s on <%s> tag. ' + 'For details, see https://reactjs.org/link/invalid-aria-props', unknownPropString, type); 3606 } 3607 } 3608 } 3609 3610 function validateProperties(type, props) { 3611 if (isCustomComponent(type, props)) { 3612 return; 3613 } 3614 3615 warnInvalidARIAProps(type, props); 3616 } 3617 3618 var didWarnValueNull = false; 3619 function validateProperties$1(type, props) { 3620 { 3621 if (type !== 'input' && type !== 'textarea' && type !== 'select') { 3622 return; 3623 } 3624 3625 if (props != null && props.value === null && !didWarnValueNull) { 3626 didWarnValueNull = true; 3627 3628 if (type === 'select' && props.multiple) { 3629 error('`value` prop on `%s` should not be null. ' + 'Consider using an empty array when `multiple` is set to `true` ' + 'to clear the component or `undefined` for uncontrolled components.', type); 3630 } else { 3631 error('`value` prop on `%s` should not be null. ' + 'Consider using an empty string to clear the component or `undefined` ' + 'for uncontrolled components.', type); 3632 } 3633 } 3634 } 3635 } 3636 3637 var validateProperty$1 = function () {}; 3638 3639 { 3640 var warnedProperties$1 = {}; 3641 var EVENT_NAME_REGEX = /^on./; 3642 var INVALID_EVENT_NAME_REGEX = /^on[^A-Z]/; 3643 var rARIA$1 = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$'); 3644 var rARIACamel$1 = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$'); 3645 3646 validateProperty$1 = function (tagName, name, value, eventRegistry) { 3647 if (hasOwnProperty.call(warnedProperties$1, name) && warnedProperties$1[name]) { 3648 return true; 3649 } 3650 3651 var lowerCasedName = name.toLowerCase(); 3652 3653 if (lowerCasedName === 'onfocusin' || lowerCasedName === 'onfocusout') { 3654 error('React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.'); 3655 3656 warnedProperties$1[name] = true; 3657 return true; 3658 } // We can't rely on the event system being injected on the server. 3659 3660 3661 if (eventRegistry != null) { 3662 var registrationNameDependencies = eventRegistry.registrationNameDependencies, 3663 possibleRegistrationNames = eventRegistry.possibleRegistrationNames; 3664 3665 if (registrationNameDependencies.hasOwnProperty(name)) { 3666 return true; 3667 } 3668 3669 var registrationName = possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? possibleRegistrationNames[lowerCasedName] : null; 3670 3671 if (registrationName != null) { 3672 error('Invalid event handler property `%s`. Did you mean `%s`?', name, registrationName); 3673 3674 warnedProperties$1[name] = true; 3675 return true; 3676 } 3677 3678 if (EVENT_NAME_REGEX.test(name)) { 3679 error('Unknown event handler property `%s`. It will be ignored.', name); 3680 3681 warnedProperties$1[name] = true; 3682 return true; 3683 } 3684 } else if (EVENT_NAME_REGEX.test(name)) { 3685 // If no event plugins have been injected, we are in a server environment. 3686 // So we can't tell if the event name is correct for sure, but we can filter 3687 // out known bad ones like `onclick`. We can't suggest a specific replacement though. 3688 if (INVALID_EVENT_NAME_REGEX.test(name)) { 3689 error('Invalid event handler property `%s`. ' + 'React events use the camelCase naming convention, for example `onClick`.', name); 3690 } 3691 3692 warnedProperties$1[name] = true; 3693 return true; 3694 } // Let the ARIA attribute hook validate ARIA attributes 3695 3696 3697 if (rARIA$1.test(name) || rARIACamel$1.test(name)) { 3698 return true; 3699 } 3700 3701 if (lowerCasedName === 'innerhtml') { 3702 error('Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.'); 3703 3704 warnedProperties$1[name] = true; 3705 return true; 3706 } 3707 3708 if (lowerCasedName === 'aria') { 3709 error('The `aria` attribute is reserved for future use in React. ' + 'Pass individual `aria-` attributes instead.'); 3710 3711 warnedProperties$1[name] = true; 3712 return true; 3713 } 3714 3715 if (lowerCasedName === 'is' && value !== null && value !== undefined && typeof value !== 'string') { 3716 error('Received a `%s` for a string attribute `is`. If this is expected, cast ' + 'the value to a string.', typeof value); 3717 3718 warnedProperties$1[name] = true; 3719 return true; 3720 } 3721 3722 if (typeof value === 'number' && isNaN(value)) { 3723 error('Received NaN for the `%s` attribute. If this is expected, cast ' + 'the value to a string.', name); 3724 3725 warnedProperties$1[name] = true; 3726 return true; 3727 } 3728 3729 var propertyInfo = getPropertyInfo(name); 3730 var isReserved = propertyInfo !== null && propertyInfo.type === RESERVED; // Known attributes should match the casing specified in the property config. 3731 3732 if (possibleStandardNames.hasOwnProperty(lowerCasedName)) { 3733 var standardName = possibleStandardNames[lowerCasedName]; 3734 3735 if (standardName !== name) { 3736 error('Invalid DOM property `%s`. Did you mean `%s`?', name, standardName); 3737 3738 warnedProperties$1[name] = true; 3739 return true; 3740 } 3741 } else if (!isReserved && name !== lowerCasedName) { 3742 // Unknown attributes should have lowercase casing since that's how they 3743 // will be cased anyway with server rendering. 3744 error('React does not recognize the `%s` prop on a DOM element. If you ' + 'intentionally want it to appear in the DOM as a custom ' + 'attribute, spell it as lowercase `%s` instead. ' + 'If you accidentally passed it from a parent component, remove ' + 'it from the DOM element.', name, lowerCasedName); 3745 3746 warnedProperties$1[name] = true; 3747 return true; 3748 } 3749 3750 if (typeof value === 'boolean' && shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) { 3751 if (value) { 3752 error('Received `%s` for a non-boolean attribute `%s`.\n\n' + 'If you want to write it to the DOM, pass a string instead: ' + '%s="%s" or %s={value.toString()}.', value, name, name, value, name); 3753 } else { 3754 error('Received `%s` for a non-boolean attribute `%s`.\n\n' + 'If you want to write it to the DOM, pass a string instead: ' + '%s="%s" or %s={value.toString()}.\n\n' + 'If you used to conditionally omit it with %s={condition && value}, ' + 'pass %s={condition ? value : undefined} instead.', value, name, name, value, name, name, name); 3755 } 3756 3757 warnedProperties$1[name] = true; 3758 return true; 3759 } // Now that we've validated casing, do not validate 3760 // data types for reserved props 3761 3762 3763 if (isReserved) { 3764 return true; 3765 } // Warn when a known attribute is a bad type 3766 3767 3768 if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) { 3769 warnedProperties$1[name] = true; 3770 return false; 3771 } // Warn when passing the strings 'false' or 'true' into a boolean prop 3772 3773 3774 if ((value === 'false' || value === 'true') && propertyInfo !== null && propertyInfo.type === BOOLEAN) { 3775 error('Received the string `%s` for the boolean attribute `%s`. ' + '%s ' + 'Did you mean %s={%s}?', value, name, value === 'false' ? 'The browser will interpret it as a truthy value.' : 'Although this works, it will not work as expected if you pass the string "false".', name, value); 3776 3777 warnedProperties$1[name] = true; 3778 return true; 3779 } 3780 3781 return true; 3782 }; 3783 } 3784 3785 var warnUnknownProperties = function (type, props, eventRegistry) { 3786 { 3787 var unknownProps = []; 3788 3789 for (var key in props) { 3790 var isValid = validateProperty$1(type, key, props[key], eventRegistry); 3791 3792 if (!isValid) { 3793 unknownProps.push(key); 3794 } 3795 } 3796 3797 var unknownPropString = unknownProps.map(function (prop) { 3798 return '`' + prop + '`'; 3799 }).join(', '); 3800 3801 if (unknownProps.length === 1) { 3802 error('Invalid value for prop %s on <%s> tag. Either remove it from the element, ' + 'or pass a string or number value to keep it in the DOM. ' + 'For details, see https://reactjs.org/link/attribute-behavior ', unknownPropString, type); 3803 } else if (unknownProps.length > 1) { 3804 error('Invalid values for props %s on <%s> tag. Either remove them from the element, ' + 'or pass a string or number value to keep them in the DOM. ' + 'For details, see https://reactjs.org/link/attribute-behavior ', unknownPropString, type); 3805 } 3806 } 3807 }; 3808 3809 function validateProperties$2(type, props, eventRegistry) { 3810 if (isCustomComponent(type, props)) { 3811 return; 3812 } 3813 3814 warnUnknownProperties(type, props, eventRegistry); 3815 } 3816 3817 var IS_EVENT_HANDLE_NON_MANAGED_NODE = 1; 3818 var IS_NON_DELEGATED = 1 << 1; 3819 var IS_CAPTURE_PHASE = 1 << 2; 3820 // set to LEGACY_FB_SUPPORT. LEGACY_FB_SUPPORT only gets set when 3821 // we call willDeferLaterForLegacyFBSupport, thus not bailing out 3822 // will result in endless cycles like an infinite loop. 3823 // We also don't want to defer during event replaying. 3824 3825 var SHOULD_NOT_PROCESS_POLYFILL_EVENT_PLUGINS = IS_EVENT_HANDLE_NON_MANAGED_NODE | IS_NON_DELEGATED | IS_CAPTURE_PHASE; 3826 3827 // This exists to avoid circular dependency between ReactDOMEventReplaying 3828 // and DOMPluginEventSystem. 3829 var currentReplayingEvent = null; 3830 function setReplayingEvent(event) { 3831 { 3832 if (currentReplayingEvent !== null) { 3833 error('Expected currently replaying event to be null. This error ' + 'is likely caused by a bug in React. Please file an issue.'); 3834 } 3835 } 3836 3837 currentReplayingEvent = event; 3838 } 3839 function resetReplayingEvent() { 3840 { 3841 if (currentReplayingEvent === null) { 3842 error('Expected currently replaying event to not be null. This error ' + 'is likely caused by a bug in React. Please file an issue.'); 3843 } 3844 } 3845 3846 currentReplayingEvent = null; 3847 } 3848 function isReplayingEvent(event) { 3849 return event === currentReplayingEvent; 3850 } 3851 3852 /** 3853 * Gets the target node from a native browser event by accounting for 3854 * inconsistencies in browser DOM APIs. 3855 * 3856 * @param {object} nativeEvent Native browser event. 3857 * @return {DOMEventTarget} Target node. 3858 */ 3859 3860 function getEventTarget(nativeEvent) { 3861 // Fallback to nativeEvent.srcElement for IE9 3862 // https://github.com/facebook/react/issues/12506 3863 var target = nativeEvent.target || nativeEvent.srcElement || window; // Normalize SVG <use> element events #4963 3864 3865 if (target.correspondingUseElement) { 3866 target = target.correspondingUseElement; 3867 } // Safari may fire events on text nodes (Node.TEXT_NODE is 3). 3868 // @see http://www.quirksmode.org/js/events_properties.html 3869 3870 3871 return target.nodeType === TEXT_NODE ? target.parentNode : target; 3872 } 3873 3874 var restoreImpl = null; 3875 var restoreTarget = null; 3876 var restoreQueue = null; 3877 3878 function restoreStateOfTarget(target) { 3879 // We perform this translation at the end of the event loop so that we 3880 // always receive the correct fiber here 3881 var internalInstance = getInstanceFromNode(target); 3882 3883 if (!internalInstance) { 3884 // Unmounted 3885 return; 3886 } 3887 3888 if (typeof restoreImpl !== 'function') { 3889 throw new Error('setRestoreImplementation() needs to be called to handle a target for controlled ' + 'events. This error is likely caused by a bug in React. Please file an issue.'); 3890 } 3891 3892 var stateNode = internalInstance.stateNode; // Guard against Fiber being unmounted. 3893 3894 if (stateNode) { 3895 var _props = getFiberCurrentPropsFromNode(stateNode); 3896 3897 restoreImpl(internalInstance.stateNode, internalInstance.type, _props); 3898 } 3899 } 3900 3901 function setRestoreImplementation(impl) { 3902 restoreImpl = impl; 3903 } 3904 function enqueueStateRestore(target) { 3905 if (restoreTarget) { 3906 if (restoreQueue) { 3907 restoreQueue.push(target); 3908 } else { 3909 restoreQueue = [target]; 3910 } 3911 } else { 3912 restoreTarget = target; 3913 } 3914 } 3915 function needsStateRestore() { 3916 return restoreTarget !== null || restoreQueue !== null; 3917 } 3918 function restoreStateIfNeeded() { 3919 if (!restoreTarget) { 3920 return; 3921 } 3922 3923 var target = restoreTarget; 3924 var queuedTargets = restoreQueue; 3925 restoreTarget = null; 3926 restoreQueue = null; 3927 restoreStateOfTarget(target); 3928 3929 if (queuedTargets) { 3930 for (var i = 0; i < queuedTargets.length; i++) { 3931 restoreStateOfTarget(queuedTargets[i]); 3932 } 3933 } 3934 } 3935 3936 // the renderer. Such as when we're dispatching events or if third party 3937 // libraries need to call batchedUpdates. Eventually, this API will go away when 3938 // everything is batched by default. We'll then have a similar API to opt-out of 3939 // scheduled work and instead do synchronous work. 3940 // Defaults 3941 3942 var batchedUpdatesImpl = function (fn, bookkeeping) { 3943 return fn(bookkeeping); 3944 }; 3945 3946 var flushSyncImpl = function () {}; 3947 3948 var isInsideEventHandler = false; 3949 3950 function finishEventHandler() { 3951 // Here we wait until all updates have propagated, which is important 3952 // when using controlled components within layers: 3953 // https://github.com/facebook/react/issues/1698 3954 // Then we restore state of any controlled component. 3955 var controlledComponentsHavePendingUpdates = needsStateRestore(); 3956 3957 if (controlledComponentsHavePendingUpdates) { 3958 // If a controlled event was fired, we may need to restore the state of 3959 // the DOM node back to the controlled value. This is necessary when React 3960 // bails out of the update without touching the DOM. 3961 // TODO: Restore state in the microtask, after the discrete updates flush, 3962 // instead of early flushing them here. 3963 flushSyncImpl(); 3964 restoreStateIfNeeded(); 3965 } 3966 } 3967 3968 function batchedUpdates(fn, a, b) { 3969 if (isInsideEventHandler) { 3970 // If we are currently inside another batch, we need to wait until it 3971 // fully completes before restoring state. 3972 return fn(a, b); 3973 } 3974 3975 isInsideEventHandler = true; 3976 3977 try { 3978 return batchedUpdatesImpl(fn, a, b); 3979 } finally { 3980 isInsideEventHandler = false; 3981 finishEventHandler(); 3982 } 3983 } // TODO: Replace with flushSync 3984 function setBatchingImplementation(_batchedUpdatesImpl, _discreteUpdatesImpl, _flushSyncImpl) { 3985 batchedUpdatesImpl = _batchedUpdatesImpl; 3986 flushSyncImpl = _flushSyncImpl; 3987 } 3988 3989 function isInteractive(tag) { 3990 return tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea'; 3991 } 3992 3993 function shouldPreventMouseEvent(name, type, props) { 3994 switch (name) { 3995 case 'onClick': 3996 case 'onClickCapture': 3997 case 'onDoubleClick': 3998 case 'onDoubleClickCapture': 3999 case 'onMouseDown': 4000 case 'onMouseDownCapture': 4001 case 'onMouseMove': 4002 case 'onMouseMoveCapture': 4003 case 'onMouseUp': 4004 case 'onMouseUpCapture': 4005 case 'onMouseEnter': 4006 return !!(props.disabled && isInteractive(type)); 4007 4008 default: 4009 return false; 4010 } 4011 } 4012 /** 4013 * @param {object} inst The instance, which is the source of events. 4014 * @param {string} registrationName Name of listener (e.g. `onClick`). 4015 * @return {?function} The stored callback. 4016 */ 4017 4018 4019 function getListener(inst, registrationName) { 4020 var stateNode = inst.stateNode; 4021 4022 if (stateNode === null) { 4023 // Work in progress (ex: onload events in incremental mode). 4024 return null; 4025 } 4026 4027 var props = getFiberCurrentPropsFromNode(stateNode); 4028 4029 if (props === null) { 4030 // Work in progress. 4031 return null; 4032 } 4033 4034 var listener = props[registrationName]; 4035 4036 if (shouldPreventMouseEvent(registrationName, inst.type, props)) { 4037 return null; 4038 } 4039 4040 if (listener && typeof listener !== 'function') { 4041 throw new Error("Expected `" + registrationName + "` listener to be a function, instead got a value of `" + typeof listener + "` type."); 4042 } 4043 4044 return listener; 4045 } 4046 4047 var passiveBrowserEventsSupported = false; // Check if browser support events with passive listeners 4048 // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support 4049 4050 if (canUseDOM) { 4051 try { 4052 var options = {}; // $FlowFixMe: Ignore Flow complaining about needing a value 4053 4054 Object.defineProperty(options, 'passive', { 4055 get: function () { 4056 passiveBrowserEventsSupported = true; 4057 } 4058 }); 4059 window.addEventListener('test', options, options); 4060 window.removeEventListener('test', options, options); 4061 } catch (e) { 4062 passiveBrowserEventsSupported = false; 4063 } 4064 } 4065 4066 function invokeGuardedCallbackProd(name, func, context, a, b, c, d, e, f) { 4067 var funcArgs = Array.prototype.slice.call(arguments, 3); 4068 4069 try { 4070 func.apply(context, funcArgs); 4071 } catch (error) { 4072 this.onError(error); 4073 } 4074 } 4075 4076 var invokeGuardedCallbackImpl = invokeGuardedCallbackProd; 4077 4078 { 4079 // In DEV mode, we swap out invokeGuardedCallback for a special version 4080 // that plays more nicely with the browser's DevTools. The idea is to preserve 4081 // "Pause on exceptions" behavior. Because React wraps all user-provided 4082 // functions in invokeGuardedCallback, and the production version of 4083 // invokeGuardedCallback uses a try-catch, all user exceptions are treated 4084 // like caught exceptions, and the DevTools won't pause unless the developer 4085 // takes the extra step of enabling pause on caught exceptions. This is 4086 // unintuitive, though, because even though React has caught the error, from 4087 // the developer's perspective, the error is uncaught. 4088 // 4089 // To preserve the expected "Pause on exceptions" behavior, we don't use a 4090 // try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake 4091 // DOM node, and call the user-provided callback from inside an event handler 4092 // for that fake event. If the callback throws, the error is "captured" using 4093 // a global event handler. But because the error happens in a different 4094 // event loop context, it does not interrupt the normal program flow. 4095 // Effectively, this gives us try-catch behavior without actually using 4096 // try-catch. Neat! 4097 // Check that the browser supports the APIs we need to implement our special 4098 // DEV version of invokeGuardedCallback 4099 if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') { 4100 var fakeNode = document.createElement('react'); 4101 4102 invokeGuardedCallbackImpl = function invokeGuardedCallbackDev(name, func, context, a, b, c, d, e, f) { 4103 // If document doesn't exist we know for sure we will crash in this method 4104 // when we call document.createEvent(). However this can cause confusing 4105 // errors: https://github.com/facebook/create-react-app/issues/3482 4106 // So we preemptively throw with a better message instead. 4107 if (typeof document === 'undefined' || document === null) { 4108 throw new Error('The `document` global was defined when React was initialized, but is not ' + 'defined anymore. This can happen in a test environment if a component ' + 'schedules an update from an asynchronous callback, but the test has already ' + 'finished running. To solve this, you can either unmount the component at ' + 'the end of your test (and ensure that any asynchronous operations get ' + 'canceled in `componentWillUnmount`), or you can change the test itself ' + 'to be asynchronous.'); 4109 } 4110 4111 var evt = document.createEvent('Event'); 4112 var didCall = false; // Keeps track of whether the user-provided callback threw an error. We 4113 // set this to true at the beginning, then set it to false right after 4114 // calling the function. If the function errors, `didError` will never be 4115 // set to false. This strategy works even if the browser is flaky and 4116 // fails to call our global error handler, because it doesn't rely on 4117 // the error event at all. 4118 4119 var didError = true; // Keeps track of the value of window.event so that we can reset it 4120 // during the callback to let user code access window.event in the 4121 // browsers that support it. 4122 4123 var windowEvent = window.event; // Keeps track of the descriptor of window.event to restore it after event 4124 // dispatching: https://github.com/facebook/react/issues/13688 4125 4126 var windowEventDescriptor = Object.getOwnPropertyDescriptor(window, 'event'); 4127 4128 function restoreAfterDispatch() { 4129 // We immediately remove the callback from event listeners so that 4130 // nested `invokeGuardedCallback` calls do not clash. Otherwise, a 4131 // nested call would trigger the fake event handlers of any call higher 4132 // in the stack. 4133 fakeNode.removeEventListener(evtType, callCallback, false); // We check for window.hasOwnProperty('event') to prevent the 4134 // window.event assignment in both IE <= 10 as they throw an error 4135 // "Member not found" in strict mode, and in Firefox which does not 4136 // support window.event. 4137 4138 if (typeof window.event !== 'undefined' && window.hasOwnProperty('event')) { 4139 window.event = windowEvent; 4140 } 4141 } // Create an event handler for our fake event. We will synchronously 4142 // dispatch our fake event using `dispatchEvent`. Inside the handler, we 4143 // call the user-provided callback. 4144 4145 4146 var funcArgs = Array.prototype.slice.call(arguments, 3); 4147 4148 function callCallback() { 4149 didCall = true; 4150 restoreAfterDispatch(); 4151 func.apply(context, funcArgs); 4152 didError = false; 4153 } // Create a global error event handler. We use this to capture the value 4154 // that was thrown. It's possible that this error handler will fire more 4155 // than once; for example, if non-React code also calls `dispatchEvent` 4156 // and a handler for that event throws. We should be resilient to most of 4157 // those cases. Even if our error event handler fires more than once, the 4158 // last error event is always used. If the callback actually does error, 4159 // we know that the last error event is the correct one, because it's not 4160 // possible for anything else to have happened in between our callback 4161 // erroring and the code that follows the `dispatchEvent` call below. If 4162 // the callback doesn't error, but the error event was fired, we know to 4163 // ignore it because `didError` will be false, as described above. 4164 4165 4166 var error; // Use this to track whether the error event is ever called. 4167 4168 var didSetError = false; 4169 var isCrossOriginError = false; 4170 4171 function handleWindowError(event) { 4172 error = event.error; 4173 didSetError = true; 4174 4175 if (error === null && event.colno === 0 && event.lineno === 0) { 4176 isCrossOriginError = true; 4177 } 4178 4179 if (event.defaultPrevented) { 4180 // Some other error handler has prevented default. 4181 // Browsers silence the error report if this happens. 4182 // We'll remember this to later decide whether to log it or not. 4183 if (error != null && typeof error === 'object') { 4184 try { 4185 error._suppressLogging = true; 4186 } catch (inner) {// Ignore. 4187 } 4188 } 4189 } 4190 } // Create a fake event type. 4191 4192 4193 var evtType = "react-" + (name ? name : 'invokeguardedcallback'); // Attach our event handlers 4194 4195 window.addEventListener('error', handleWindowError); 4196 fakeNode.addEventListener(evtType, callCallback, false); // Synchronously dispatch our fake event. If the user-provided function 4197 // errors, it will trigger our global error handler. 4198 4199 evt.initEvent(evtType, false, false); 4200 fakeNode.dispatchEvent(evt); 4201 4202 if (windowEventDescriptor) { 4203 Object.defineProperty(window, 'event', windowEventDescriptor); 4204 } 4205 4206 if (didCall && didError) { 4207 if (!didSetError) { 4208 // The callback errored, but the error event never fired. 4209 // eslint-disable-next-line react-internal/prod-error-codes 4210 error = new Error('An error was thrown inside one of your components, but React ' + "doesn't know what it was. This is likely due to browser " + 'flakiness. React does its best to preserve the "Pause on ' + 'exceptions" behavior of the DevTools, which requires some ' + "DEV-mode only tricks. It's possible that these don't work in " + 'your browser. Try triggering the error in production mode, ' + 'or switching to a modern browser. If you suspect that this is ' + 'actually an issue with React, please file an issue.'); 4211 } else if (isCrossOriginError) { 4212 // eslint-disable-next-line react-internal/prod-error-codes 4213 error = new Error("A cross-origin error was thrown. React doesn't have access to " + 'the actual error object in development. ' + 'See https://reactjs.org/link/crossorigin-error for more information.'); 4214 } 4215 4216 this.onError(error); 4217 } // Remove our event listeners 4218 4219 4220 window.removeEventListener('error', handleWindowError); 4221 4222 if (!didCall) { 4223 // Something went really wrong, and our event was not dispatched. 4224 // https://github.com/facebook/react/issues/16734 4225 // https://github.com/facebook/react/issues/16585 4226 // Fall back to the production implementation. 4227 restoreAfterDispatch(); 4228 return invokeGuardedCallbackProd.apply(this, arguments); 4229 } 4230 }; 4231 } 4232 } 4233 4234 var invokeGuardedCallbackImpl$1 = invokeGuardedCallbackImpl; 4235 4236 var hasError = false; 4237 var caughtError = null; // Used by event system to capture/rethrow the first error. 4238 4239 var hasRethrowError = false; 4240 var rethrowError = null; 4241 var reporter = { 4242 onError: function (error) { 4243 hasError = true; 4244 caughtError = error; 4245 } 4246 }; 4247 /** 4248 * Call a function while guarding against errors that happens within it. 4249 * Returns an error if it throws, otherwise null. 4250 * 4251 * In production, this is implemented using a try-catch. The reason we don't 4252 * use a try-catch directly is so that we can swap out a different 4253 * implementation in DEV mode. 4254 * 4255 * @param {String} name of the guard to use for logging or debugging 4256 * @param {Function} func The function to invoke 4257 * @param {*} context The context to use when calling the function 4258 * @param {...*} args Arguments for function 4259 */ 4260 4261 function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) { 4262 hasError = false; 4263 caughtError = null; 4264 invokeGuardedCallbackImpl$1.apply(reporter, arguments); 4265 } 4266 /** 4267 * Same as invokeGuardedCallback, but instead of returning an error, it stores 4268 * it in a global so it can be rethrown by `rethrowCaughtError` later. 4269 * TODO: See if caughtError and rethrowError can be unified. 4270 * 4271 * @param {String} name of the guard to use for logging or debugging 4272 * @param {Function} func The function to invoke 4273 * @param {*} context The context to use when calling the function 4274 * @param {...*} args Arguments for function 4275 */ 4276 4277 function invokeGuardedCallbackAndCatchFirstError(name, func, context, a, b, c, d, e, f) { 4278 invokeGuardedCallback.apply(this, arguments); 4279 4280 if (hasError) { 4281 var error = clearCaughtError(); 4282 4283 if (!hasRethrowError) { 4284 hasRethrowError = true; 4285 rethrowError = error; 4286 } 4287 } 4288 } 4289 /** 4290 * During execution of guarded functions we will capture the first error which 4291 * we will rethrow to be handled by the top level error handler. 4292 */ 4293 4294 function rethrowCaughtError() { 4295 if (hasRethrowError) { 4296 var error = rethrowError; 4297 hasRethrowError = false; 4298 rethrowError = null; 4299 throw error; 4300 } 4301 } 4302 function hasCaughtError() { 4303 return hasError; 4304 } 4305 function clearCaughtError() { 4306 if (hasError) { 4307 var error = caughtError; 4308 hasError = false; 4309 caughtError = null; 4310 return error; 4311 } else { 4312 throw new Error('clearCaughtError was called but no error was captured. This error ' + 'is likely caused by a bug in React. Please file an issue.'); 4313 } 4314 } 4315 4316 var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; 4317 var _ReactInternals$Sched = ReactInternals.Scheduler, 4318 unstable_cancelCallback = _ReactInternals$Sched.unstable_cancelCallback, 4319 unstable_now = _ReactInternals$Sched.unstable_now, 4320 unstable_scheduleCallback = _ReactInternals$Sched.unstable_scheduleCallback, 4321 unstable_shouldYield = _ReactInternals$Sched.unstable_shouldYield, 4322 unstable_requestPaint = _ReactInternals$Sched.unstable_requestPaint, 4323 unstable_getFirstCallbackNode = _ReactInternals$Sched.unstable_getFirstCallbackNode, 4324 unstable_runWithPriority = _ReactInternals$Sched.unstable_runWithPriority, 4325 unstable_next = _ReactInternals$Sched.unstable_next, 4326 unstable_continueExecution = _ReactInternals$Sched.unstable_continueExecution, 4327 unstable_pauseExecution = _ReactInternals$Sched.unstable_pauseExecution, 4328 unstable_getCurrentPriorityLevel = _ReactInternals$Sched.unstable_getCurrentPriorityLevel, 4329 unstable_ImmediatePriority = _ReactInternals$Sched.unstable_ImmediatePriority, 4330 unstable_UserBlockingPriority = _ReactInternals$Sched.unstable_UserBlockingPriority, 4331 unstable_NormalPriority = _ReactInternals$Sched.unstable_NormalPriority, 4332 unstable_LowPriority = _ReactInternals$Sched.unstable_LowPriority, 4333 unstable_IdlePriority = _ReactInternals$Sched.unstable_IdlePriority, 4334 unstable_forceFrameRate = _ReactInternals$Sched.unstable_forceFrameRate, 4335 unstable_flushAllWithoutAsserting = _ReactInternals$Sched.unstable_flushAllWithoutAsserting, 4336 unstable_yieldValue = _ReactInternals$Sched.unstable_yieldValue, 4337 unstable_setDisableYieldValue = _ReactInternals$Sched.unstable_setDisableYieldValue; 4338 4339 /** 4340 * `ReactInstanceMap` maintains a mapping from a public facing stateful 4341 * instance (key) and the internal representation (value). This allows public 4342 * methods to accept the user facing instance as an argument and map them back 4343 * to internal methods. 4344 * 4345 * Note that this module is currently shared and assumed to be stateless. 4346 * If this becomes an actual Map, that will break. 4347 */ 4348 function get(key) { 4349 return key._reactInternals; 4350 } 4351 function has(key) { 4352 return key._reactInternals !== undefined; 4353 } 4354 function set(key, value) { 4355 key._reactInternals = value; 4356 } 4357 4358 // Don't change these two values. They're used by React Dev Tools. 4359 var NoFlags = 4360 /* */ 4361 0; 4362 var PerformedWork = 4363 /* */ 4364 1; // You can change the rest (and add more). 4365 4366 var Placement = 4367 /* */ 4368 2; 4369 var Update = 4370 /* */ 4371 4; 4372 var ChildDeletion = 4373 /* */ 4374 16; 4375 var ContentReset = 4376 /* */ 4377 32; 4378 var Callback = 4379 /* */ 4380 64; 4381 var DidCapture = 4382 /* */ 4383 128; 4384 var ForceClientRender = 4385 /* */ 4386 256; 4387 var Ref = 4388 /* */ 4389 512; 4390 var Snapshot = 4391 /* */ 4392 1024; 4393 var Passive = 4394 /* */ 4395 2048; 4396 var Hydrating = 4397 /* */ 4398 4096; 4399 var Visibility = 4400 /* */ 4401 8192; 4402 var StoreConsistency = 4403 /* */ 4404 16384; 4405 var LifecycleEffectMask = Passive | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit) 4406 4407 var HostEffectMask = 4408 /* */ 4409 32767; // These are not really side effects, but we still reuse this field. 4410 4411 var Incomplete = 4412 /* */ 4413 32768; 4414 var ShouldCapture = 4415 /* */ 4416 65536; 4417 var ForceUpdateForLegacySuspense = 4418 /* */ 4419 131072; 4420 var Forked = 4421 /* */ 4422 1048576; // Static tags describe aspects of a fiber that are not specific to a render, 4423 // e.g. a fiber uses a passive effect (even if there are no updates on this particular render). 4424 // This enables us to defer more work in the unmount case, 4425 // since we can defer traversing the tree during layout to look for Passive effects, 4426 // and instead rely on the static flag as a signal that there may be cleanup work. 4427 4428 var RefStatic = 4429 /* */ 4430 2097152; 4431 var LayoutStatic = 4432 /* */ 4433 4194304; 4434 var PassiveStatic = 4435 /* */ 4436 8388608; // These flags allow us to traverse to fibers that have effects on mount 4437 // without traversing the entire tree after every commit for 4438 // double invoking 4439 4440 var MountLayoutDev = 4441 /* */ 4442 16777216; 4443 var MountPassiveDev = 4444 /* */ 4445 33554432; // Groups of flags that are used in the commit phase to skip over trees that 4446 // don't contain effects, by checking subtreeFlags. 4447 4448 var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility 4449 // flag logic (see #20043) 4450 Update | Snapshot | ( 0); 4451 var MutationMask = Placement | Update | ChildDeletion | ContentReset | Ref | Hydrating | Visibility; 4452 var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask 4453 4454 var PassiveMask = Passive | ChildDeletion; // Union of tags that don't get reset on clones. 4455 // This allows certain concepts to persist without recalculating them, 4456 // e.g. whether a subtree contains passive effects or portals. 4457 4458 var StaticMask = LayoutStatic | PassiveStatic | RefStatic; 4459 4460 var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; 4461 function getNearestMountedFiber(fiber) { 4462 var node = fiber; 4463 var nearestMounted = fiber; 4464 4465 if (!fiber.alternate) { 4466 // If there is no alternate, this might be a new tree that isn't inserted 4467 // yet. If it is, then it will have a pending insertion effect on it. 4468 var nextNode = node; 4469 4470 do { 4471 node = nextNode; 4472 4473 if ((node.flags & (Placement | Hydrating)) !== NoFlags) { 4474 // This is an insertion or in-progress hydration. The nearest possible 4475 // mounted fiber is the parent but we need to continue to figure out 4476 // if that one is still mounted. 4477 nearestMounted = node.return; 4478 } 4479 4480 nextNode = node.return; 4481 } while (nextNode); 4482 } else { 4483 while (node.return) { 4484 node = node.return; 4485 } 4486 } 4487 4488 if (node.tag === HostRoot) { 4489 // TODO: Check if this was a nested HostRoot when used with 4490 // renderContainerIntoSubtree. 4491 return nearestMounted; 4492 } // If we didn't hit the root, that means that we're in an disconnected tree 4493 // that has been unmounted. 4494 4495 4496 return null; 4497 } 4498 function getSuspenseInstanceFromFiber(fiber) { 4499 if (fiber.tag === SuspenseComponent) { 4500 var suspenseState = fiber.memoizedState; 4501 4502 if (suspenseState === null) { 4503 var current = fiber.alternate; 4504 4505 if (current !== null) { 4506 suspenseState = current.memoizedState; 4507 } 4508 } 4509 4510 if (suspenseState !== null) { 4511 return suspenseState.dehydrated; 4512 } 4513 } 4514 4515 return null; 4516 } 4517 function getContainerFromFiber(fiber) { 4518 return fiber.tag === HostRoot ? fiber.stateNode.containerInfo : null; 4519 } 4520 function isFiberMounted(fiber) { 4521 return getNearestMountedFiber(fiber) === fiber; 4522 } 4523 function isMounted(component) { 4524 { 4525 var owner = ReactCurrentOwner.current; 4526 4527 if (owner !== null && owner.tag === ClassComponent) { 4528 var ownerFiber = owner; 4529 var instance = ownerFiber.stateNode; 4530 4531 if (!instance._warnedAboutRefsInRender) { 4532 error('%s is accessing isMounted inside its render() function. ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', getComponentNameFromFiber(ownerFiber) || 'A component'); 4533 } 4534 4535 instance._warnedAboutRefsInRender = true; 4536 } 4537 } 4538 4539 var fiber = get(component); 4540 4541 if (!fiber) { 4542 return false; 4543 } 4544 4545 return getNearestMountedFiber(fiber) === fiber; 4546 } 4547 4548 function assertIsMounted(fiber) { 4549 if (getNearestMountedFiber(fiber) !== fiber) { 4550 throw new Error('Unable to find node on an unmounted component.'); 4551 } 4552 } 4553 4554 function findCurrentFiberUsingSlowPath(fiber) { 4555 var alternate = fiber.alternate; 4556 4557 if (!alternate) { 4558 // If there is no alternate, then we only need to check if it is mounted. 4559 var nearestMounted = getNearestMountedFiber(fiber); 4560 4561 if (nearestMounted === null) { 4562 throw new Error('Unable to find node on an unmounted component.'); 4563 } 4564 4565 if (nearestMounted !== fiber) { 4566 return null; 4567 } 4568 4569 return fiber; 4570 } // If we have two possible branches, we'll walk backwards up to the root 4571 // to see what path the root points to. On the way we may hit one of the 4572 // special cases and we'll deal with them. 4573 4574 4575 var a = fiber; 4576 var b = alternate; 4577 4578 while (true) { 4579 var parentA = a.return; 4580 4581 if (parentA === null) { 4582 // We're at the root. 4583 break; 4584 } 4585 4586 var parentB = parentA.alternate; 4587 4588 if (parentB === null) { 4589 // There is no alternate. This is an unusual case. Currently, it only 4590 // happens when a Suspense component is hidden. An extra fragment fiber 4591 // is inserted in between the Suspense fiber and its children. Skip 4592 // over this extra fragment fiber and proceed to the next parent. 4593 var nextParent = parentA.return; 4594 4595 if (nextParent !== null) { 4596 a = b = nextParent; 4597 continue; 4598 } // If there's no parent, we're at the root. 4599 4600 4601 break; 4602 } // If both copies of the parent fiber point to the same child, we can 4603 // assume that the child is current. This happens when we bailout on low 4604 // priority: the bailed out fiber's child reuses the current child. 4605 4606 4607 if (parentA.child === parentB.child) { 4608 var child = parentA.child; 4609 4610 while (child) { 4611 if (child === a) { 4612 // We've determined that A is the current branch. 4613 assertIsMounted(parentA); 4614 return fiber; 4615 } 4616 4617 if (child === b) { 4618 // We've determined that B is the current branch. 4619 assertIsMounted(parentA); 4620 return alternate; 4621 } 4622 4623 child = child.sibling; 4624 } // We should never have an alternate for any mounting node. So the only 4625 // way this could possibly happen is if this was unmounted, if at all. 4626 4627 4628 throw new Error('Unable to find node on an unmounted component.'); 4629 } 4630 4631 if (a.return !== b.return) { 4632 // The return pointer of A and the return pointer of B point to different 4633 // fibers. We assume that return pointers never criss-cross, so A must 4634 // belong to the child set of A.return, and B must belong to the child 4635 // set of B.return. 4636 a = parentA; 4637 b = parentB; 4638 } else { 4639 // The return pointers point to the same fiber. We'll have to use the 4640 // default, slow path: scan the child sets of each parent alternate to see 4641 // which child belongs to which set. 4642 // 4643 // Search parent A's child set 4644 var didFindChild = false; 4645 var _child = parentA.child; 4646 4647 while (_child) { 4648 if (_child === a) { 4649 didFindChild = true; 4650 a = parentA; 4651 b = parentB; 4652 break; 4653 } 4654 4655 if (_child === b) { 4656 didFindChild = true; 4657 b = parentA; 4658 a = parentB; 4659 break; 4660 } 4661 4662 _child = _child.sibling; 4663 } 4664 4665 if (!didFindChild) { 4666 // Search parent B's child set 4667 _child = parentB.child; 4668 4669 while (_child) { 4670 if (_child === a) { 4671 didFindChild = true; 4672 a = parentB; 4673 b = parentA; 4674 break; 4675 } 4676 4677 if (_child === b) { 4678 didFindChild = true; 4679 b = parentB; 4680 a = parentA; 4681 break; 4682 } 4683 4684 _child = _child.sibling; 4685 } 4686 4687 if (!didFindChild) { 4688 throw new Error('Child was not found in either parent set. This indicates a bug ' + 'in React related to the return pointer. Please file an issue.'); 4689 } 4690 } 4691 } 4692 4693 if (a.alternate !== b) { 4694 throw new Error("Return fibers should always be each others' alternates. " + 'This error is likely caused by a bug in React. Please file an issue.'); 4695 } 4696 } // If the root is not a host container, we're in a disconnected tree. I.e. 4697 // unmounted. 4698 4699 4700 if (a.tag !== HostRoot) { 4701 throw new Error('Unable to find node on an unmounted component.'); 4702 } 4703 4704 if (a.stateNode.current === a) { 4705 // We've determined that A is the current branch. 4706 return fiber; 4707 } // Otherwise B has to be current branch. 4708 4709 4710 return alternate; 4711 } 4712 function findCurrentHostFiber(parent) { 4713 var currentParent = findCurrentFiberUsingSlowPath(parent); 4714 return currentParent !== null ? findCurrentHostFiberImpl(currentParent) : null; 4715 } 4716 4717 function findCurrentHostFiberImpl(node) { 4718 // Next we'll drill down this component to find the first HostComponent/Text. 4719 if (node.tag === HostComponent || node.tag === HostText) { 4720 return node; 4721 } 4722 4723 var child = node.child; 4724 4725 while (child !== null) { 4726 var match = findCurrentHostFiberImpl(child); 4727 4728 if (match !== null) { 4729 return match; 4730 } 4731 4732 child = child.sibling; 4733 } 4734 4735 return null; 4736 } 4737 4738 function findCurrentHostFiberWithNoPortals(parent) { 4739 var currentParent = findCurrentFiberUsingSlowPath(parent); 4740 return currentParent !== null ? findCurrentHostFiberWithNoPortalsImpl(currentParent) : null; 4741 } 4742 4743 function findCurrentHostFiberWithNoPortalsImpl(node) { 4744 // Next we'll drill down this component to find the first HostComponent/Text. 4745 if (node.tag === HostComponent || node.tag === HostText) { 4746 return node; 4747 } 4748 4749 var child = node.child; 4750 4751 while (child !== null) { 4752 if (child.tag !== HostPortal) { 4753 var match = findCurrentHostFiberWithNoPortalsImpl(child); 4754 4755 if (match !== null) { 4756 return match; 4757 } 4758 } 4759 4760 child = child.sibling; 4761 } 4762 4763 return null; 4764 } 4765 4766 // This module only exists as an ESM wrapper around the external CommonJS 4767 var scheduleCallback = unstable_scheduleCallback; 4768 var cancelCallback = unstable_cancelCallback; 4769 var shouldYield = unstable_shouldYield; 4770 var requestPaint = unstable_requestPaint; 4771 var now = unstable_now; 4772 var getCurrentPriorityLevel = unstable_getCurrentPriorityLevel; 4773 var ImmediatePriority = unstable_ImmediatePriority; 4774 var UserBlockingPriority = unstable_UserBlockingPriority; 4775 var NormalPriority = unstable_NormalPriority; 4776 var LowPriority = unstable_LowPriority; 4777 var IdlePriority = unstable_IdlePriority; 4778 // this doesn't actually exist on the scheduler, but it *does* 4779 // on scheduler/unstable_mock, which we'll need for internal testing 4780 var unstable_yieldValue$1 = unstable_yieldValue; 4781 var unstable_setDisableYieldValue$1 = unstable_setDisableYieldValue; 4782 4783 var rendererID = null; 4784 var injectedHook = null; 4785 var injectedProfilingHooks = null; 4786 var hasLoggedError = false; 4787 var isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined'; 4788 function injectInternals(internals) { 4789 if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') { 4790 // No DevTools 4791 return false; 4792 } 4793 4794 var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; 4795 4796 if (hook.isDisabled) { 4797 // This isn't a real property on the hook, but it can be set to opt out 4798 // of DevTools integration and associated warnings and logs. 4799 // https://github.com/facebook/react/issues/3877 4800 return true; 4801 } 4802 4803 if (!hook.supportsFiber) { 4804 { 4805 error('The installed version of React DevTools is too old and will not work ' + 'with the current version of React. Please update React DevTools. ' + 'https://reactjs.org/link/react-devtools'); 4806 } // DevTools exists, even though it doesn't support Fiber. 4807 4808 4809 return true; 4810 } 4811 4812 try { 4813 if (enableSchedulingProfiler) { 4814 // Conditionally inject these hooks only if Timeline profiler is supported by this build. 4815 // This gives DevTools a way to feature detect that isn't tied to version number 4816 // (since profiling and timeline are controlled by different feature flags). 4817 internals = assign({}, internals, { 4818 getLaneLabelMap: getLaneLabelMap, 4819 injectProfilingHooks: injectProfilingHooks 4820 }); 4821 } 4822 4823 rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. 4824 4825 injectedHook = hook; 4826 } catch (err) { 4827 // Catch all errors because it is unsafe to throw during initialization. 4828 { 4829 error('React instrumentation encountered an error: %s.', err); 4830 } 4831 } 4832 4833 if (hook.checkDCE) { 4834 // This is the real DevTools. 4835 return true; 4836 } else { 4837 // This is likely a hook installed by Fast Refresh runtime. 4838 return false; 4839 } 4840 } 4841 function onScheduleRoot(root, children) { 4842 { 4843 if (injectedHook && typeof injectedHook.onScheduleFiberRoot === 'function') { 4844 try { 4845 injectedHook.onScheduleFiberRoot(rendererID, root, children); 4846 } catch (err) { 4847 if ( !hasLoggedError) { 4848 hasLoggedError = true; 4849 4850 error('React instrumentation encountered an error: %s', err); 4851 } 4852 } 4853 } 4854 } 4855 } 4856 function onCommitRoot(root, eventPriority) { 4857 if (injectedHook && typeof injectedHook.onCommitFiberRoot === 'function') { 4858 try { 4859 var didError = (root.current.flags & DidCapture) === DidCapture; 4860 4861 if (enableProfilerTimer) { 4862 var schedulerPriority; 4863 4864 switch (eventPriority) { 4865 case DiscreteEventPriority: 4866 schedulerPriority = ImmediatePriority; 4867 break; 4868 4869 case ContinuousEventPriority: 4870 schedulerPriority = UserBlockingPriority; 4871 break; 4872 4873 case DefaultEventPriority: 4874 schedulerPriority = NormalPriority; 4875 break; 4876 4877 case IdleEventPriority: 4878 schedulerPriority = IdlePriority; 4879 break; 4880 4881 default: 4882 schedulerPriority = NormalPriority; 4883 break; 4884 } 4885 4886 injectedHook.onCommitFiberRoot(rendererID, root, schedulerPriority, didError); 4887 } else { 4888 injectedHook.onCommitFiberRoot(rendererID, root, undefined, didError); 4889 } 4890 } catch (err) { 4891 { 4892 if (!hasLoggedError) { 4893 hasLoggedError = true; 4894 4895 error('React instrumentation encountered an error: %s', err); 4896 } 4897 } 4898 } 4899 } 4900 } 4901 function onPostCommitRoot(root) { 4902 if (injectedHook && typeof injectedHook.onPostCommitFiberRoot === 'function') { 4903 try { 4904 injectedHook.onPostCommitFiberRoot(rendererID, root); 4905 } catch (err) { 4906 { 4907 if (!hasLoggedError) { 4908 hasLoggedError = true; 4909 4910 error('React instrumentation encountered an error: %s', err); 4911 } 4912 } 4913 } 4914 } 4915 } 4916 function onCommitUnmount(fiber) { 4917 if (injectedHook && typeof injectedHook.onCommitFiberUnmount === 'function') { 4918 try { 4919 injectedHook.onCommitFiberUnmount(rendererID, fiber); 4920 } catch (err) { 4921 { 4922 if (!hasLoggedError) { 4923 hasLoggedError = true; 4924 4925 error('React instrumentation encountered an error: %s', err); 4926 } 4927 } 4928 } 4929 } 4930 } 4931 function setIsStrictModeForDevtools(newIsStrictMode) { 4932 { 4933 if (typeof unstable_yieldValue$1 === 'function') { 4934 // We're in a test because Scheduler.unstable_yieldValue only exists 4935 // in SchedulerMock. To reduce the noise in strict mode tests, 4936 // suppress warnings and disable scheduler yielding during the double render 4937 unstable_setDisableYieldValue$1(newIsStrictMode); 4938 setSuppressWarning(newIsStrictMode); 4939 } 4940 4941 if (injectedHook && typeof injectedHook.setStrictMode === 'function') { 4942 try { 4943 injectedHook.setStrictMode(rendererID, newIsStrictMode); 4944 } catch (err) { 4945 { 4946 if (!hasLoggedError) { 4947 hasLoggedError = true; 4948 4949 error('React instrumentation encountered an error: %s', err); 4950 } 4951 } 4952 } 4953 } 4954 } 4955 } // Profiler API hooks 4956 4957 function injectProfilingHooks(profilingHooks) { 4958 injectedProfilingHooks = profilingHooks; 4959 } 4960 4961 function getLaneLabelMap() { 4962 { 4963 var map = new Map(); 4964 var lane = 1; 4965 4966 for (var index = 0; index < TotalLanes; index++) { 4967 var label = getLabelForLane(lane); 4968 map.set(lane, label); 4969 lane *= 2; 4970 } 4971 4972 return map; 4973 } 4974 } 4975 4976 function markCommitStarted(lanes) { 4977 { 4978 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markCommitStarted === 'function') { 4979 injectedProfilingHooks.markCommitStarted(lanes); 4980 } 4981 } 4982 } 4983 function markCommitStopped() { 4984 { 4985 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markCommitStopped === 'function') { 4986 injectedProfilingHooks.markCommitStopped(); 4987 } 4988 } 4989 } 4990 function markComponentRenderStarted(fiber) { 4991 { 4992 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentRenderStarted === 'function') { 4993 injectedProfilingHooks.markComponentRenderStarted(fiber); 4994 } 4995 } 4996 } 4997 function markComponentRenderStopped() { 4998 { 4999 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentRenderStopped === 'function') { 5000 injectedProfilingHooks.markComponentRenderStopped(); 5001 } 5002 } 5003 } 5004 function markComponentPassiveEffectMountStarted(fiber) { 5005 { 5006 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectMountStarted === 'function') { 5007 injectedProfilingHooks.markComponentPassiveEffectMountStarted(fiber); 5008 } 5009 } 5010 } 5011 function markComponentPassiveEffectMountStopped() { 5012 { 5013 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectMountStopped === 'function') { 5014 injectedProfilingHooks.markComponentPassiveEffectMountStopped(); 5015 } 5016 } 5017 } 5018 function markComponentPassiveEffectUnmountStarted(fiber) { 5019 { 5020 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStarted === 'function') { 5021 injectedProfilingHooks.markComponentPassiveEffectUnmountStarted(fiber); 5022 } 5023 } 5024 } 5025 function markComponentPassiveEffectUnmountStopped() { 5026 { 5027 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStopped === 'function') { 5028 injectedProfilingHooks.markComponentPassiveEffectUnmountStopped(); 5029 } 5030 } 5031 } 5032 function markComponentLayoutEffectMountStarted(fiber) { 5033 { 5034 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectMountStarted === 'function') { 5035 injectedProfilingHooks.markComponentLayoutEffectMountStarted(fiber); 5036 } 5037 } 5038 } 5039 function markComponentLayoutEffectMountStopped() { 5040 { 5041 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectMountStopped === 'function') { 5042 injectedProfilingHooks.markComponentLayoutEffectMountStopped(); 5043 } 5044 } 5045 } 5046 function markComponentLayoutEffectUnmountStarted(fiber) { 5047 { 5048 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted === 'function') { 5049 injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber); 5050 } 5051 } 5052 } 5053 function markComponentLayoutEffectUnmountStopped() { 5054 { 5055 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped === 'function') { 5056 injectedProfilingHooks.markComponentLayoutEffectUnmountStopped(); 5057 } 5058 } 5059 } 5060 function markComponentErrored(fiber, thrownValue, lanes) { 5061 { 5062 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentErrored === 'function') { 5063 injectedProfilingHooks.markComponentErrored(fiber, thrownValue, lanes); 5064 } 5065 } 5066 } 5067 function markComponentSuspended(fiber, wakeable, lanes) { 5068 { 5069 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentSuspended === 'function') { 5070 injectedProfilingHooks.markComponentSuspended(fiber, wakeable, lanes); 5071 } 5072 } 5073 } 5074 function markLayoutEffectsStarted(lanes) { 5075 { 5076 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markLayoutEffectsStarted === 'function') { 5077 injectedProfilingHooks.markLayoutEffectsStarted(lanes); 5078 } 5079 } 5080 } 5081 function markLayoutEffectsStopped() { 5082 { 5083 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markLayoutEffectsStopped === 'function') { 5084 injectedProfilingHooks.markLayoutEffectsStopped(); 5085 } 5086 } 5087 } 5088 function markPassiveEffectsStarted(lanes) { 5089 { 5090 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markPassiveEffectsStarted === 'function') { 5091 injectedProfilingHooks.markPassiveEffectsStarted(lanes); 5092 } 5093 } 5094 } 5095 function markPassiveEffectsStopped() { 5096 { 5097 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markPassiveEffectsStopped === 'function') { 5098 injectedProfilingHooks.markPassiveEffectsStopped(); 5099 } 5100 } 5101 } 5102 function markRenderStarted(lanes) { 5103 { 5104 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderStarted === 'function') { 5105 injectedProfilingHooks.markRenderStarted(lanes); 5106 } 5107 } 5108 } 5109 function markRenderYielded() { 5110 { 5111 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderYielded === 'function') { 5112 injectedProfilingHooks.markRenderYielded(); 5113 } 5114 } 5115 } 5116 function markRenderStopped() { 5117 { 5118 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderStopped === 'function') { 5119 injectedProfilingHooks.markRenderStopped(); 5120 } 5121 } 5122 } 5123 function markRenderScheduled(lane) { 5124 { 5125 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderScheduled === 'function') { 5126 injectedProfilingHooks.markRenderScheduled(lane); 5127 } 5128 } 5129 } 5130 function markForceUpdateScheduled(fiber, lane) { 5131 { 5132 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markForceUpdateScheduled === 'function') { 5133 injectedProfilingHooks.markForceUpdateScheduled(fiber, lane); 5134 } 5135 } 5136 } 5137 function markStateUpdateScheduled(fiber, lane) { 5138 { 5139 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markStateUpdateScheduled === 'function') { 5140 injectedProfilingHooks.markStateUpdateScheduled(fiber, lane); 5141 } 5142 } 5143 } 5144 5145 var NoMode = 5146 /* */ 5147 0; // TODO: Remove ConcurrentMode by reading from the root tag instead 5148 5149 var ConcurrentMode = 5150 /* */ 5151 1; 5152 var ProfileMode = 5153 /* */ 5154 2; 5155 var StrictLegacyMode = 5156 /* */ 5157 8; 5158 var StrictEffectsMode = 5159 /* */ 5160 16; 5161 5162 // TODO: This is pretty well supported by browsers. Maybe we can drop it. 5163 var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; // Count leading zeros. 5164 // Based on: 5165 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 5166 5167 var log = Math.log; 5168 var LN2 = Math.LN2; 5169 5170 function clz32Fallback(x) { 5171 var asUint = x >>> 0; 5172 5173 if (asUint === 0) { 5174 return 32; 5175 } 5176 5177 return 31 - (log(asUint) / LN2 | 0) | 0; 5178 } 5179 5180 // If those values are changed that package should be rebuilt and redeployed. 5181 5182 var TotalLanes = 31; 5183 var NoLanes = 5184 /* */ 5185 0; 5186 var NoLane = 5187 /* */ 5188 0; 5189 var SyncLane = 5190 /* */ 5191 1; 5192 var InputContinuousHydrationLane = 5193 /* */ 5194 2; 5195 var InputContinuousLane = 5196 /* */ 5197 4; 5198 var DefaultHydrationLane = 5199 /* */ 5200 8; 5201 var DefaultLane = 5202 /* */ 5203 16; 5204 var TransitionHydrationLane = 5205 /* */ 5206 32; 5207 var TransitionLanes = 5208 /* */ 5209 4194240; 5210 var TransitionLane1 = 5211 /* */ 5212 64; 5213 var TransitionLane2 = 5214 /* */ 5215 128; 5216 var TransitionLane3 = 5217 /* */ 5218 256; 5219 var TransitionLane4 = 5220 /* */ 5221 512; 5222 var TransitionLane5 = 5223 /* */ 5224 1024; 5225 var TransitionLane6 = 5226 /* */ 5227 2048; 5228 var TransitionLane7 = 5229 /* */ 5230 4096; 5231 var TransitionLane8 = 5232 /* */ 5233 8192; 5234 var TransitionLane9 = 5235 /* */ 5236 16384; 5237 var TransitionLane10 = 5238 /* */ 5239 32768; 5240 var TransitionLane11 = 5241 /* */ 5242 65536; 5243 var TransitionLane12 = 5244 /* */ 5245 131072; 5246 var TransitionLane13 = 5247 /* */ 5248 262144; 5249 var TransitionLane14 = 5250 /* */ 5251 524288; 5252 var TransitionLane15 = 5253 /* */ 5254 1048576; 5255 var TransitionLane16 = 5256 /* */ 5257 2097152; 5258 var RetryLanes = 5259 /* */ 5260 130023424; 5261 var RetryLane1 = 5262 /* */ 5263 4194304; 5264 var RetryLane2 = 5265 /* */ 5266 8388608; 5267 var RetryLane3 = 5268 /* */ 5269 16777216; 5270 var RetryLane4 = 5271 /* */ 5272 33554432; 5273 var RetryLane5 = 5274 /* */ 5275 67108864; 5276 var SomeRetryLane = RetryLane1; 5277 var SelectiveHydrationLane = 5278 /* */ 5279 134217728; 5280 var NonIdleLanes = 5281 /* */ 5282 268435455; 5283 var IdleHydrationLane = 5284 /* */ 5285 268435456; 5286 var IdleLane = 5287 /* */ 5288 536870912; 5289 var OffscreenLane = 5290 /* */ 5291 1073741824; // This function is used for the experimental timeline (react-devtools-timeline) 5292 // It should be kept in sync with the Lanes values above. 5293 5294 function getLabelForLane(lane) { 5295 { 5296 if (lane & SyncLane) { 5297 return 'Sync'; 5298 } 5299 5300 if (lane & InputContinuousHydrationLane) { 5301 return 'InputContinuousHydration'; 5302 } 5303 5304 if (lane & InputContinuousLane) { 5305 return 'InputContinuous'; 5306 } 5307 5308 if (lane & DefaultHydrationLane) { 5309 return 'DefaultHydration'; 5310 } 5311 5312 if (lane & DefaultLane) { 5313 return 'Default'; 5314 } 5315 5316 if (lane & TransitionHydrationLane) { 5317 return 'TransitionHydration'; 5318 } 5319 5320 if (lane & TransitionLanes) { 5321 return 'Transition'; 5322 } 5323 5324 if (lane & RetryLanes) { 5325 return 'Retry'; 5326 } 5327 5328 if (lane & SelectiveHydrationLane) { 5329 return 'SelectiveHydration'; 5330 } 5331 5332 if (lane & IdleHydrationLane) { 5333 return 'IdleHydration'; 5334 } 5335 5336 if (lane & IdleLane) { 5337 return 'Idle'; 5338 } 5339 5340 if (lane & OffscreenLane) { 5341 return 'Offscreen'; 5342 } 5343 } 5344 } 5345 var NoTimestamp = -1; 5346 var nextTransitionLane = TransitionLane1; 5347 var nextRetryLane = RetryLane1; 5348 5349 function getHighestPriorityLanes(lanes) { 5350 switch (getHighestPriorityLane(lanes)) { 5351 case SyncLane: 5352 return SyncLane; 5353 5354 case InputContinuousHydrationLane: 5355 return InputContinuousHydrationLane; 5356 5357 case InputContinuousLane: 5358 return InputContinuousLane; 5359 5360 case DefaultHydrationLane: 5361 return DefaultHydrationLane; 5362 5363 case DefaultLane: 5364 return DefaultLane; 5365 5366 case TransitionHydrationLane: 5367 return TransitionHydrationLane; 5368 5369 case TransitionLane1: 5370 case TransitionLane2: 5371 case TransitionLane3: 5372 case TransitionLane4: 5373 case TransitionLane5: 5374 case TransitionLane6: 5375 case TransitionLane7: 5376 case TransitionLane8: 5377 case TransitionLane9: 5378 case TransitionLane10: 5379 case TransitionLane11: 5380 case TransitionLane12: 5381 case TransitionLane13: 5382 case TransitionLane14: 5383 case TransitionLane15: 5384 case TransitionLane16: 5385 return lanes & TransitionLanes; 5386 5387 case RetryLane1: 5388 case RetryLane2: 5389 case RetryLane3: 5390 case RetryLane4: 5391 case RetryLane5: 5392 return lanes & RetryLanes; 5393 5394 case SelectiveHydrationLane: 5395 return SelectiveHydrationLane; 5396 5397 case IdleHydrationLane: 5398 return IdleHydrationLane; 5399 5400 case IdleLane: 5401 return IdleLane; 5402 5403 case OffscreenLane: 5404 return OffscreenLane; 5405 5406 default: 5407 { 5408 error('Should have found matching lanes. This is a bug in React.'); 5409 } // This shouldn't be reachable, but as a fallback, return the entire bitmask. 5410 5411 5412 return lanes; 5413 } 5414 } 5415 5416 function getNextLanes(root, wipLanes) { 5417 // Early bailout if there's no pending work left. 5418 var pendingLanes = root.pendingLanes; 5419 5420 if (pendingLanes === NoLanes) { 5421 return NoLanes; 5422 } 5423 5424 var nextLanes = NoLanes; 5425 var suspendedLanes = root.suspendedLanes; 5426 var pingedLanes = root.pingedLanes; // Do not work on any idle work until all the non-idle work has finished, 5427 // even if the work is suspended. 5428 5429 var nonIdlePendingLanes = pendingLanes & NonIdleLanes; 5430 5431 if (nonIdlePendingLanes !== NoLanes) { 5432 var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; 5433 5434 if (nonIdleUnblockedLanes !== NoLanes) { 5435 nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); 5436 } else { 5437 var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; 5438 5439 if (nonIdlePingedLanes !== NoLanes) { 5440 nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); 5441 } 5442 } 5443 } else { 5444 // The only remaining work is Idle. 5445 var unblockedLanes = pendingLanes & ~suspendedLanes; 5446 5447 if (unblockedLanes !== NoLanes) { 5448 nextLanes = getHighestPriorityLanes(unblockedLanes); 5449 } else { 5450 if (pingedLanes !== NoLanes) { 5451 nextLanes = getHighestPriorityLanes(pingedLanes); 5452 } 5453 } 5454 } 5455 5456 if (nextLanes === NoLanes) { 5457 // This should only be reachable if we're suspended 5458 // TODO: Consider warning in this path if a fallback timer is not scheduled. 5459 return NoLanes; 5460 } // If we're already in the middle of a render, switching lanes will interrupt 5461 // it and we'll lose our progress. We should only do this if the new lanes are 5462 // higher priority. 5463 5464 5465 if (wipLanes !== NoLanes && wipLanes !== nextLanes && // If we already suspended with a delay, then interrupting is fine. Don't 5466 // bother waiting until the root is complete. 5467 (wipLanes & suspendedLanes) === NoLanes) { 5468 var nextLane = getHighestPriorityLane(nextLanes); 5469 var wipLane = getHighestPriorityLane(wipLanes); 5470 5471 if ( // Tests whether the next lane is equal or lower priority than the wip 5472 // one. This works because the bits decrease in priority as you go left. 5473 nextLane >= wipLane || // Default priority updates should not interrupt transition updates. The 5474 // only difference between default updates and transition updates is that 5475 // default updates do not support refresh transitions. 5476 nextLane === DefaultLane && (wipLane & TransitionLanes) !== NoLanes) { 5477 // Keep working on the existing in-progress tree. Do not interrupt. 5478 return wipLanes; 5479 } 5480 } 5481 5482 if ((nextLanes & InputContinuousLane) !== NoLanes) { 5483 // When updates are sync by default, we entangle continuous priority updates 5484 // and default updates, so they render in the same batch. The only reason 5485 // they use separate lanes is because continuous updates should interrupt 5486 // transitions, but default updates should not. 5487 nextLanes |= pendingLanes & DefaultLane; 5488 } // Check for entangled lanes and add them to the batch. 5489 // 5490 // A lane is said to be entangled with another when it's not allowed to render 5491 // in a batch that does not also include the other lane. Typically we do this 5492 // when multiple updates have the same source, and we only want to respond to 5493 // the most recent event from that source. 5494 // 5495 // Note that we apply entanglements *after* checking for partial work above. 5496 // This means that if a lane is entangled during an interleaved event while 5497 // it's already rendering, we won't interrupt it. This is intentional, since 5498 // entanglement is usually "best effort": we'll try our best to render the 5499 // lanes in the same batch, but it's not worth throwing out partially 5500 // completed work in order to do it. 5501 // TODO: Reconsider this. The counter-argument is that the partial work 5502 // represents an intermediate state, which we don't want to show to the user. 5503 // And by spending extra time finishing it, we're increasing the amount of 5504 // time it takes to show the final state, which is what they are actually 5505 // waiting for. 5506 // 5507 // For those exceptions where entanglement is semantically important, like 5508 // useMutableSource, we should ensure that there is no partial work at the 5509 // time we apply the entanglement. 5510 5511 5512 var entangledLanes = root.entangledLanes; 5513 5514 if (entangledLanes !== NoLanes) { 5515 var entanglements = root.entanglements; 5516 var lanes = nextLanes & entangledLanes; 5517 5518 while (lanes > 0) { 5519 var index = pickArbitraryLaneIndex(lanes); 5520 var lane = 1 << index; 5521 nextLanes |= entanglements[index]; 5522 lanes &= ~lane; 5523 } 5524 } 5525 5526 return nextLanes; 5527 } 5528 function getMostRecentEventTime(root, lanes) { 5529 var eventTimes = root.eventTimes; 5530 var mostRecentEventTime = NoTimestamp; 5531 5532 while (lanes > 0) { 5533 var index = pickArbitraryLaneIndex(lanes); 5534 var lane = 1 << index; 5535 var eventTime = eventTimes[index]; 5536 5537 if (eventTime > mostRecentEventTime) { 5538 mostRecentEventTime = eventTime; 5539 } 5540 5541 lanes &= ~lane; 5542 } 5543 5544 return mostRecentEventTime; 5545 } 5546 5547 function computeExpirationTime(lane, currentTime) { 5548 switch (lane) { 5549 case SyncLane: 5550 case InputContinuousHydrationLane: 5551 case InputContinuousLane: 5552 // User interactions should expire slightly more quickly. 5553 // 5554 // NOTE: This is set to the corresponding constant as in Scheduler.js. 5555 // When we made it larger, a product metric in www regressed, suggesting 5556 // there's a user interaction that's being starved by a series of 5557 // synchronous updates. If that theory is correct, the proper solution is 5558 // to fix the starvation. However, this scenario supports the idea that 5559 // expiration times are an important safeguard when starvation 5560 // does happen. 5561 return currentTime + 250; 5562 5563 case DefaultHydrationLane: 5564 case DefaultLane: 5565 case TransitionHydrationLane: 5566 case TransitionLane1: 5567 case TransitionLane2: 5568 case TransitionLane3: 5569 case TransitionLane4: 5570 case TransitionLane5: 5571 case TransitionLane6: 5572 case TransitionLane7: 5573 case TransitionLane8: 5574 case TransitionLane9: 5575 case TransitionLane10: 5576 case TransitionLane11: 5577 case TransitionLane12: 5578 case TransitionLane13: 5579 case TransitionLane14: 5580 case TransitionLane15: 5581 case TransitionLane16: 5582 return currentTime + 5000; 5583 5584 case RetryLane1: 5585 case RetryLane2: 5586 case RetryLane3: 5587 case RetryLane4: 5588 case RetryLane5: 5589 // TODO: Retries should be allowed to expire if they are CPU bound for 5590 // too long, but when I made this change it caused a spike in browser 5591 // crashes. There must be some other underlying bug; not super urgent but 5592 // ideally should figure out why and fix it. Unfortunately we don't have 5593 // a repro for the crashes, only detected via production metrics. 5594 return NoTimestamp; 5595 5596 case SelectiveHydrationLane: 5597 case IdleHydrationLane: 5598 case IdleLane: 5599 case OffscreenLane: 5600 // Anything idle priority or lower should never expire. 5601 return NoTimestamp; 5602 5603 default: 5604 { 5605 error('Should have found matching lanes. This is a bug in React.'); 5606 } 5607 5608 return NoTimestamp; 5609 } 5610 } 5611 5612 function markStarvedLanesAsExpired(root, currentTime) { 5613 // TODO: This gets called every time we yield. We can optimize by storing 5614 // the earliest expiration time on the root. Then use that to quickly bail out 5615 // of this function. 5616 var pendingLanes = root.pendingLanes; 5617 var suspendedLanes = root.suspendedLanes; 5618 var pingedLanes = root.pingedLanes; 5619 var expirationTimes = root.expirationTimes; // Iterate through the pending lanes and check if we've reached their 5620 // expiration time. If so, we'll assume the update is being starved and mark 5621 // it as expired to force it to finish. 5622 5623 var lanes = pendingLanes; 5624 5625 while (lanes > 0) { 5626 var index = pickArbitraryLaneIndex(lanes); 5627 var lane = 1 << index; 5628 var expirationTime = expirationTimes[index]; 5629 5630 if (expirationTime === NoTimestamp) { 5631 // Found a pending lane with no expiration time. If it's not suspended, or 5632 // if it's pinged, assume it's CPU-bound. Compute a new expiration time 5633 // using the current time. 5634 if ((lane & suspendedLanes) === NoLanes || (lane & pingedLanes) !== NoLanes) { 5635 // Assumes timestamps are monotonically increasing. 5636 expirationTimes[index] = computeExpirationTime(lane, currentTime); 5637 } 5638 } else if (expirationTime <= currentTime) { 5639 // This lane expired 5640 root.expiredLanes |= lane; 5641 } 5642 5643 lanes &= ~lane; 5644 } 5645 } // This returns the highest priority pending lanes regardless of whether they 5646 // are suspended. 5647 5648 function getHighestPriorityPendingLanes(root) { 5649 return getHighestPriorityLanes(root.pendingLanes); 5650 } 5651 function getLanesToRetrySynchronouslyOnError(root) { 5652 var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; 5653 5654 if (everythingButOffscreen !== NoLanes) { 5655 return everythingButOffscreen; 5656 } 5657 5658 if (everythingButOffscreen & OffscreenLane) { 5659 return OffscreenLane; 5660 } 5661 5662 return NoLanes; 5663 } 5664 function includesSyncLane(lanes) { 5665 return (lanes & SyncLane) !== NoLanes; 5666 } 5667 function includesNonIdleWork(lanes) { 5668 return (lanes & NonIdleLanes) !== NoLanes; 5669 } 5670 function includesOnlyRetries(lanes) { 5671 return (lanes & RetryLanes) === lanes; 5672 } 5673 function includesOnlyNonUrgentLanes(lanes) { 5674 var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; 5675 return (lanes & UrgentLanes) === NoLanes; 5676 } 5677 function includesOnlyTransitions(lanes) { 5678 return (lanes & TransitionLanes) === lanes; 5679 } 5680 function includesBlockingLane(root, lanes) { 5681 5682 var SyncDefaultLanes = InputContinuousHydrationLane | InputContinuousLane | DefaultHydrationLane | DefaultLane; 5683 return (lanes & SyncDefaultLanes) !== NoLanes; 5684 } 5685 function includesExpiredLane(root, lanes) { 5686 // This is a separate check from includesBlockingLane because a lane can 5687 // expire after a render has already started. 5688 return (lanes & root.expiredLanes) !== NoLanes; 5689 } 5690 function isTransitionLane(lane) { 5691 return (lane & TransitionLanes) !== NoLanes; 5692 } 5693 function claimNextTransitionLane() { 5694 // Cycle through the lanes, assigning each new transition to the next lane. 5695 // In most cases, this means every transition gets its own lane, until we 5696 // run out of lanes and cycle back to the beginning. 5697 var lane = nextTransitionLane; 5698 nextTransitionLane <<= 1; 5699 5700 if ((nextTransitionLane & TransitionLanes) === NoLanes) { 5701 nextTransitionLane = TransitionLane1; 5702 } 5703 5704 return lane; 5705 } 5706 function claimNextRetryLane() { 5707 var lane = nextRetryLane; 5708 nextRetryLane <<= 1; 5709 5710 if ((nextRetryLane & RetryLanes) === NoLanes) { 5711 nextRetryLane = RetryLane1; 5712 } 5713 5714 return lane; 5715 } 5716 function getHighestPriorityLane(lanes) { 5717 return lanes & -lanes; 5718 } 5719 function pickArbitraryLane(lanes) { 5720 // This wrapper function gets inlined. Only exists so to communicate that it 5721 // doesn't matter which bit is selected; you can pick any bit without 5722 // affecting the algorithms where its used. Here I'm using 5723 // getHighestPriorityLane because it requires the fewest operations. 5724 return getHighestPriorityLane(lanes); 5725 } 5726 5727 function pickArbitraryLaneIndex(lanes) { 5728 return 31 - clz32(lanes); 5729 } 5730 5731 function laneToIndex(lane) { 5732 return pickArbitraryLaneIndex(lane); 5733 } 5734 5735 function includesSomeLane(a, b) { 5736 return (a & b) !== NoLanes; 5737 } 5738 function isSubsetOfLanes(set, subset) { 5739 return (set & subset) === subset; 5740 } 5741 function mergeLanes(a, b) { 5742 return a | b; 5743 } 5744 function removeLanes(set, subset) { 5745 return set & ~subset; 5746 } 5747 function intersectLanes(a, b) { 5748 return a & b; 5749 } // Seems redundant, but it changes the type from a single lane (used for 5750 // updates) to a group of lanes (used for flushing work). 5751 5752 function laneToLanes(lane) { 5753 return lane; 5754 } 5755 function higherPriorityLane(a, b) { 5756 // This works because the bit ranges decrease in priority as you go left. 5757 return a !== NoLane && a < b ? a : b; 5758 } 5759 function createLaneMap(initial) { 5760 // Intentionally pushing one by one. 5761 // https://v8.dev/blog/elements-kinds#avoid-creating-holes 5762 var laneMap = []; 5763 5764 for (var i = 0; i < TotalLanes; i++) { 5765 laneMap.push(initial); 5766 } 5767 5768 return laneMap; 5769 } 5770 function markRootUpdated(root, updateLane, eventTime) { 5771 root.pendingLanes |= updateLane; // If there are any suspended transitions, it's possible this new update 5772 // could unblock them. Clear the suspended lanes so that we can try rendering 5773 // them again. 5774 // 5775 // TODO: We really only need to unsuspend only lanes that are in the 5776 // `subtreeLanes` of the updated fiber, or the update lanes of the return 5777 // path. This would exclude suspended updates in an unrelated sibling tree, 5778 // since there's no way for this update to unblock it. 5779 // 5780 // We don't do this if the incoming update is idle, because we never process 5781 // idle updates until after all the regular updates have finished; there's no 5782 // way it could unblock a transition. 5783 5784 if (updateLane !== IdleLane) { 5785 root.suspendedLanes = NoLanes; 5786 root.pingedLanes = NoLanes; 5787 } 5788 5789 var eventTimes = root.eventTimes; 5790 var index = laneToIndex(updateLane); // We can always overwrite an existing timestamp because we prefer the most 5791 // recent event, and we assume time is monotonically increasing. 5792 5793 eventTimes[index] = eventTime; 5794 } 5795 function markRootSuspended(root, suspendedLanes) { 5796 root.suspendedLanes |= suspendedLanes; 5797 root.pingedLanes &= ~suspendedLanes; // The suspended lanes are no longer CPU-bound. Clear their expiration times. 5798 5799 var expirationTimes = root.expirationTimes; 5800 var lanes = suspendedLanes; 5801 5802 while (lanes > 0) { 5803 var index = pickArbitraryLaneIndex(lanes); 5804 var lane = 1 << index; 5805 expirationTimes[index] = NoTimestamp; 5806 lanes &= ~lane; 5807 } 5808 } 5809 function markRootPinged(root, pingedLanes, eventTime) { 5810 root.pingedLanes |= root.suspendedLanes & pingedLanes; 5811 } 5812 function markRootFinished(root, remainingLanes) { 5813 var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; 5814 root.pendingLanes = remainingLanes; // Let's try everything again 5815 5816 root.suspendedLanes = NoLanes; 5817 root.pingedLanes = NoLanes; 5818 root.expiredLanes &= remainingLanes; 5819 root.mutableReadLanes &= remainingLanes; 5820 root.entangledLanes &= remainingLanes; 5821 var entanglements = root.entanglements; 5822 var eventTimes = root.eventTimes; 5823 var expirationTimes = root.expirationTimes; // Clear the lanes that no longer have pending work 5824 5825 var lanes = noLongerPendingLanes; 5826 5827 while (lanes > 0) { 5828 var index = pickArbitraryLaneIndex(lanes); 5829 var lane = 1 << index; 5830 entanglements[index] = NoLanes; 5831 eventTimes[index] = NoTimestamp; 5832 expirationTimes[index] = NoTimestamp; 5833 lanes &= ~lane; 5834 } 5835 } 5836 function markRootEntangled(root, entangledLanes) { 5837 // In addition to entangling each of the given lanes with each other, we also 5838 // have to consider _transitive_ entanglements. For each lane that is already 5839 // entangled with *any* of the given lanes, that lane is now transitively 5840 // entangled with *all* the given lanes. 5841 // 5842 // Translated: If C is entangled with A, then entangling A with B also 5843 // entangles C with B. 5844 // 5845 // If this is hard to grasp, it might help to intentionally break this 5846 // function and look at the tests that fail in ReactTransition-test.js. Try 5847 // commenting out one of the conditions below. 5848 var rootEntangledLanes = root.entangledLanes |= entangledLanes; 5849 var entanglements = root.entanglements; 5850 var lanes = rootEntangledLanes; 5851 5852 while (lanes) { 5853 var index = pickArbitraryLaneIndex(lanes); 5854 var lane = 1 << index; 5855 5856 if ( // Is this one of the newly entangled lanes? 5857 lane & entangledLanes | // Is this lane transitively entangled with the newly entangled lanes? 5858 entanglements[index] & entangledLanes) { 5859 entanglements[index] |= entangledLanes; 5860 } 5861 5862 lanes &= ~lane; 5863 } 5864 } 5865 function getBumpedLaneForHydration(root, renderLanes) { 5866 var renderLane = getHighestPriorityLane(renderLanes); 5867 var lane; 5868 5869 switch (renderLane) { 5870 case InputContinuousLane: 5871 lane = InputContinuousHydrationLane; 5872 break; 5873 5874 case DefaultLane: 5875 lane = DefaultHydrationLane; 5876 break; 5877 5878 case TransitionLane1: 5879 case TransitionLane2: 5880 case TransitionLane3: 5881 case TransitionLane4: 5882 case TransitionLane5: 5883 case TransitionLane6: 5884 case TransitionLane7: 5885 case TransitionLane8: 5886 case TransitionLane9: 5887 case TransitionLane10: 5888 case TransitionLane11: 5889 case TransitionLane12: 5890 case TransitionLane13: 5891 case TransitionLane14: 5892 case TransitionLane15: 5893 case TransitionLane16: 5894 case RetryLane1: 5895 case RetryLane2: 5896 case RetryLane3: 5897 case RetryLane4: 5898 case RetryLane5: 5899 lane = TransitionHydrationLane; 5900 break; 5901 5902 case IdleLane: 5903 lane = IdleHydrationLane; 5904 break; 5905 5906 default: 5907 // Everything else is already either a hydration lane, or shouldn't 5908 // be retried at a hydration lane. 5909 lane = NoLane; 5910 break; 5911 } // Check if the lane we chose is suspended. If so, that indicates that we 5912 // already attempted and failed to hydrate at that level. Also check if we're 5913 // already rendering that lane, which is rare but could happen. 5914 5915 5916 if ((lane & (root.suspendedLanes | renderLanes)) !== NoLane) { 5917 // Give up trying to hydrate and fall back to client render. 5918 return NoLane; 5919 } 5920 5921 return lane; 5922 } 5923 function addFiberToLanesMap(root, fiber, lanes) { 5924 5925 if (!isDevToolsPresent) { 5926 return; 5927 } 5928 5929 var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; 5930 5931 while (lanes > 0) { 5932 var index = laneToIndex(lanes); 5933 var lane = 1 << index; 5934 var updaters = pendingUpdatersLaneMap[index]; 5935 updaters.add(fiber); 5936 lanes &= ~lane; 5937 } 5938 } 5939 function movePendingFibersToMemoized(root, lanes) { 5940 5941 if (!isDevToolsPresent) { 5942 return; 5943 } 5944 5945 var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; 5946 var memoizedUpdaters = root.memoizedUpdaters; 5947 5948 while (lanes > 0) { 5949 var index = laneToIndex(lanes); 5950 var lane = 1 << index; 5951 var updaters = pendingUpdatersLaneMap[index]; 5952 5953 if (updaters.size > 0) { 5954 updaters.forEach(function (fiber) { 5955 var alternate = fiber.alternate; 5956 5957 if (alternate === null || !memoizedUpdaters.has(alternate)) { 5958 memoizedUpdaters.add(fiber); 5959 } 5960 }); 5961 updaters.clear(); 5962 } 5963 5964 lanes &= ~lane; 5965 } 5966 } 5967 function getTransitionsForLanes(root, lanes) { 5968 { 5969 return null; 5970 } 5971 } 5972 5973 var DiscreteEventPriority = SyncLane; 5974 var ContinuousEventPriority = InputContinuousLane; 5975 var DefaultEventPriority = DefaultLane; 5976 var IdleEventPriority = IdleLane; 5977 var currentUpdatePriority = NoLane; 5978 function getCurrentUpdatePriority() { 5979 return currentUpdatePriority; 5980 } 5981 function setCurrentUpdatePriority(newPriority) { 5982 currentUpdatePriority = newPriority; 5983 } 5984 function runWithPriority(priority, fn) { 5985 var previousPriority = currentUpdatePriority; 5986 5987 try { 5988 currentUpdatePriority = priority; 5989 return fn(); 5990 } finally { 5991 currentUpdatePriority = previousPriority; 5992 } 5993 } 5994 function higherEventPriority(a, b) { 5995 return a !== 0 && a < b ? a : b; 5996 } 5997 function lowerEventPriority(a, b) { 5998 return a === 0 || a > b ? a : b; 5999 } 6000 function isHigherEventPriority(a, b) { 6001 return a !== 0 && a < b; 6002 } 6003 function lanesToEventPriority(lanes) { 6004 var lane = getHighestPriorityLane(lanes); 6005 6006 if (!isHigherEventPriority(DiscreteEventPriority, lane)) { 6007 return DiscreteEventPriority; 6008 } 6009 6010 if (!isHigherEventPriority(ContinuousEventPriority, lane)) { 6011 return ContinuousEventPriority; 6012 } 6013 6014 if (includesNonIdleWork(lane)) { 6015 return DefaultEventPriority; 6016 } 6017 6018 return IdleEventPriority; 6019 } 6020 6021 // This is imported by the event replaying implementation in React DOM. It's 6022 // in a separate file to break a circular dependency between the renderer and 6023 // the reconciler. 6024 function isRootDehydrated(root) { 6025 var currentState = root.current.memoizedState; 6026 return currentState.isDehydrated; 6027 } 6028 6029 var _attemptSynchronousHydration; 6030 6031 function setAttemptSynchronousHydration(fn) { 6032 _attemptSynchronousHydration = fn; 6033 } 6034 function attemptSynchronousHydration(fiber) { 6035 _attemptSynchronousHydration(fiber); 6036 } 6037 var attemptContinuousHydration; 6038 function setAttemptContinuousHydration(fn) { 6039 attemptContinuousHydration = fn; 6040 } 6041 var attemptHydrationAtCurrentPriority; 6042 function setAttemptHydrationAtCurrentPriority(fn) { 6043 attemptHydrationAtCurrentPriority = fn; 6044 } 6045 var getCurrentUpdatePriority$1; 6046 function setGetCurrentUpdatePriority(fn) { 6047 getCurrentUpdatePriority$1 = fn; 6048 } 6049 var attemptHydrationAtPriority; 6050 function setAttemptHydrationAtPriority(fn) { 6051 attemptHydrationAtPriority = fn; 6052 } // TODO: Upgrade this definition once we're on a newer version of Flow that 6053 // has this definition built-in. 6054 6055 var hasScheduledReplayAttempt = false; // The queue of discrete events to be replayed. 6056 6057 var queuedDiscreteEvents = []; // Indicates if any continuous event targets are non-null for early bailout. 6058 // if the last target was dehydrated. 6059 6060 var queuedFocus = null; 6061 var queuedDrag = null; 6062 var queuedMouse = null; // For pointer events there can be one latest event per pointerId. 6063 6064 var queuedPointers = new Map(); 6065 var queuedPointerCaptures = new Map(); // We could consider replaying selectionchange and touchmoves too. 6066 6067 var queuedExplicitHydrationTargets = []; 6068 var discreteReplayableEvents = ['mousedown', 'mouseup', 'touchcancel', 'touchend', 'touchstart', 'auxclick', 'dblclick', 'pointercancel', 'pointerdown', 'pointerup', 'dragend', 'dragstart', 'drop', 'compositionend', 'compositionstart', 'keydown', 'keypress', 'keyup', 'input', 'textInput', // Intentionally camelCase 6069 'copy', 'cut', 'paste', 'click', 'change', 'contextmenu', 'reset', 'submit']; 6070 function isDiscreteEventThatRequiresHydration(eventType) { 6071 return discreteReplayableEvents.indexOf(eventType) > -1; 6072 } 6073 6074 function createQueuedReplayableEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6075 return { 6076 blockedOn: blockedOn, 6077 domEventName: domEventName, 6078 eventSystemFlags: eventSystemFlags, 6079 nativeEvent: nativeEvent, 6080 targetContainers: [targetContainer] 6081 }; 6082 } 6083 6084 function clearIfContinuousEvent(domEventName, nativeEvent) { 6085 switch (domEventName) { 6086 case 'focusin': 6087 case 'focusout': 6088 queuedFocus = null; 6089 break; 6090 6091 case 'dragenter': 6092 case 'dragleave': 6093 queuedDrag = null; 6094 break; 6095 6096 case 'mouseover': 6097 case 'mouseout': 6098 queuedMouse = null; 6099 break; 6100 6101 case 'pointerover': 6102 case 'pointerout': 6103 { 6104 var pointerId = nativeEvent.pointerId; 6105 queuedPointers.delete(pointerId); 6106 break; 6107 } 6108 6109 case 'gotpointercapture': 6110 case 'lostpointercapture': 6111 { 6112 var _pointerId = nativeEvent.pointerId; 6113 queuedPointerCaptures.delete(_pointerId); 6114 break; 6115 } 6116 } 6117 } 6118 6119 function accumulateOrCreateContinuousQueuedReplayableEvent(existingQueuedEvent, blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6120 if (existingQueuedEvent === null || existingQueuedEvent.nativeEvent !== nativeEvent) { 6121 var queuedEvent = createQueuedReplayableEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent); 6122 6123 if (blockedOn !== null) { 6124 var _fiber2 = getInstanceFromNode(blockedOn); 6125 6126 if (_fiber2 !== null) { 6127 // Attempt to increase the priority of this target. 6128 attemptContinuousHydration(_fiber2); 6129 } 6130 } 6131 6132 return queuedEvent; 6133 } // If we have already queued this exact event, then it's because 6134 // the different event systems have different DOM event listeners. 6135 // We can accumulate the flags, and the targetContainers, and 6136 // store a single event to be replayed. 6137 6138 6139 existingQueuedEvent.eventSystemFlags |= eventSystemFlags; 6140 var targetContainers = existingQueuedEvent.targetContainers; 6141 6142 if (targetContainer !== null && targetContainers.indexOf(targetContainer) === -1) { 6143 targetContainers.push(targetContainer); 6144 } 6145 6146 return existingQueuedEvent; 6147 } 6148 6149 function queueIfContinuousEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6150 // These set relatedTarget to null because the replayed event will be treated as if we 6151 // moved from outside the window (no target) onto the target once it hydrates. 6152 // Instead of mutating we could clone the event. 6153 switch (domEventName) { 6154 case 'focusin': 6155 { 6156 var focusEvent = nativeEvent; 6157 queuedFocus = accumulateOrCreateContinuousQueuedReplayableEvent(queuedFocus, blockedOn, domEventName, eventSystemFlags, targetContainer, focusEvent); 6158 return true; 6159 } 6160 6161 case 'dragenter': 6162 { 6163 var dragEvent = nativeEvent; 6164 queuedDrag = accumulateOrCreateContinuousQueuedReplayableEvent(queuedDrag, blockedOn, domEventName, eventSystemFlags, targetContainer, dragEvent); 6165 return true; 6166 } 6167 6168 case 'mouseover': 6169 { 6170 var mouseEvent = nativeEvent; 6171 queuedMouse = accumulateOrCreateContinuousQueuedReplayableEvent(queuedMouse, blockedOn, domEventName, eventSystemFlags, targetContainer, mouseEvent); 6172 return true; 6173 } 6174 6175 case 'pointerover': 6176 { 6177 var pointerEvent = nativeEvent; 6178 var pointerId = pointerEvent.pointerId; 6179 queuedPointers.set(pointerId, accumulateOrCreateContinuousQueuedReplayableEvent(queuedPointers.get(pointerId) || null, blockedOn, domEventName, eventSystemFlags, targetContainer, pointerEvent)); 6180 return true; 6181 } 6182 6183 case 'gotpointercapture': 6184 { 6185 var _pointerEvent = nativeEvent; 6186 var _pointerId2 = _pointerEvent.pointerId; 6187 queuedPointerCaptures.set(_pointerId2, accumulateOrCreateContinuousQueuedReplayableEvent(queuedPointerCaptures.get(_pointerId2) || null, blockedOn, domEventName, eventSystemFlags, targetContainer, _pointerEvent)); 6188 return true; 6189 } 6190 } 6191 6192 return false; 6193 } // Check if this target is unblocked. Returns true if it's unblocked. 6194 6195 function attemptExplicitHydrationTarget(queuedTarget) { 6196 // TODO: This function shares a lot of logic with findInstanceBlockingEvent. 6197 // Try to unify them. It's a bit tricky since it would require two return 6198 // values. 6199 var targetInst = getClosestInstanceFromNode(queuedTarget.target); 6200 6201 if (targetInst !== null) { 6202 var nearestMounted = getNearestMountedFiber(targetInst); 6203 6204 if (nearestMounted !== null) { 6205 var tag = nearestMounted.tag; 6206 6207 if (tag === SuspenseComponent) { 6208 var instance = getSuspenseInstanceFromFiber(nearestMounted); 6209 6210 if (instance !== null) { 6211 // We're blocked on hydrating this boundary. 6212 // Increase its priority. 6213 queuedTarget.blockedOn = instance; 6214 attemptHydrationAtPriority(queuedTarget.priority, function () { 6215 attemptHydrationAtCurrentPriority(nearestMounted); 6216 }); 6217 return; 6218 } 6219 } else if (tag === HostRoot) { 6220 var root = nearestMounted.stateNode; 6221 6222 if (isRootDehydrated(root)) { 6223 queuedTarget.blockedOn = getContainerFromFiber(nearestMounted); // We don't currently have a way to increase the priority of 6224 // a root other than sync. 6225 6226 return; 6227 } 6228 } 6229 } 6230 } 6231 6232 queuedTarget.blockedOn = null; 6233 } 6234 6235 function queueExplicitHydrationTarget(target) { 6236 // TODO: This will read the priority if it's dispatched by the React 6237 // event system but not native events. Should read window.event.type, like 6238 // we do for updates (getCurrentEventPriority). 6239 var updatePriority = getCurrentUpdatePriority$1(); 6240 var queuedTarget = { 6241 blockedOn: null, 6242 target: target, 6243 priority: updatePriority 6244 }; 6245 var i = 0; 6246 6247 for (; i < queuedExplicitHydrationTargets.length; i++) { 6248 // Stop once we hit the first target with lower priority than 6249 if (!isHigherEventPriority(updatePriority, queuedExplicitHydrationTargets[i].priority)) { 6250 break; 6251 } 6252 } 6253 6254 queuedExplicitHydrationTargets.splice(i, 0, queuedTarget); 6255 6256 if (i === 0) { 6257 attemptExplicitHydrationTarget(queuedTarget); 6258 } 6259 } 6260 6261 function attemptReplayContinuousQueuedEvent(queuedEvent) { 6262 if (queuedEvent.blockedOn !== null) { 6263 return false; 6264 } 6265 6266 var targetContainers = queuedEvent.targetContainers; 6267 6268 while (targetContainers.length > 0) { 6269 var targetContainer = targetContainers[0]; 6270 var nextBlockedOn = findInstanceBlockingEvent(queuedEvent.domEventName, queuedEvent.eventSystemFlags, targetContainer, queuedEvent.nativeEvent); 6271 6272 if (nextBlockedOn === null) { 6273 { 6274 var nativeEvent = queuedEvent.nativeEvent; 6275 var nativeEventClone = new nativeEvent.constructor(nativeEvent.type, nativeEvent); 6276 setReplayingEvent(nativeEventClone); 6277 nativeEvent.target.dispatchEvent(nativeEventClone); 6278 resetReplayingEvent(); 6279 } 6280 } else { 6281 // We're still blocked. Try again later. 6282 var _fiber3 = getInstanceFromNode(nextBlockedOn); 6283 6284 if (_fiber3 !== null) { 6285 attemptContinuousHydration(_fiber3); 6286 } 6287 6288 queuedEvent.blockedOn = nextBlockedOn; 6289 return false; 6290 } // This target container was successfully dispatched. Try the next. 6291 6292 6293 targetContainers.shift(); 6294 } 6295 6296 return true; 6297 } 6298 6299 function attemptReplayContinuousQueuedEventInMap(queuedEvent, key, map) { 6300 if (attemptReplayContinuousQueuedEvent(queuedEvent)) { 6301 map.delete(key); 6302 } 6303 } 6304 6305 function replayUnblockedEvents() { 6306 hasScheduledReplayAttempt = false; 6307 6308 6309 if (queuedFocus !== null && attemptReplayContinuousQueuedEvent(queuedFocus)) { 6310 queuedFocus = null; 6311 } 6312 6313 if (queuedDrag !== null && attemptReplayContinuousQueuedEvent(queuedDrag)) { 6314 queuedDrag = null; 6315 } 6316 6317 if (queuedMouse !== null && attemptReplayContinuousQueuedEvent(queuedMouse)) { 6318 queuedMouse = null; 6319 } 6320 6321 queuedPointers.forEach(attemptReplayContinuousQueuedEventInMap); 6322 queuedPointerCaptures.forEach(attemptReplayContinuousQueuedEventInMap); 6323 } 6324 6325 function scheduleCallbackIfUnblocked(queuedEvent, unblocked) { 6326 if (queuedEvent.blockedOn === unblocked) { 6327 queuedEvent.blockedOn = null; 6328 6329 if (!hasScheduledReplayAttempt) { 6330 hasScheduledReplayAttempt = true; // Schedule a callback to attempt replaying as many events as are 6331 // now unblocked. This first might not actually be unblocked yet. 6332 // We could check it early to avoid scheduling an unnecessary callback. 6333 6334 unstable_scheduleCallback(unstable_NormalPriority, replayUnblockedEvents); 6335 } 6336 } 6337 } 6338 6339 function retryIfBlockedOn(unblocked) { 6340 // Mark anything that was blocked on this as no longer blocked 6341 // and eligible for a replay. 6342 if (queuedDiscreteEvents.length > 0) { 6343 scheduleCallbackIfUnblocked(queuedDiscreteEvents[0], unblocked); // This is a exponential search for each boundary that commits. I think it's 6344 // worth it because we expect very few discrete events to queue up and once 6345 // we are actually fully unblocked it will be fast to replay them. 6346 6347 for (var i = 1; i < queuedDiscreteEvents.length; i++) { 6348 var queuedEvent = queuedDiscreteEvents[i]; 6349 6350 if (queuedEvent.blockedOn === unblocked) { 6351 queuedEvent.blockedOn = null; 6352 } 6353 } 6354 } 6355 6356 if (queuedFocus !== null) { 6357 scheduleCallbackIfUnblocked(queuedFocus, unblocked); 6358 } 6359 6360 if (queuedDrag !== null) { 6361 scheduleCallbackIfUnblocked(queuedDrag, unblocked); 6362 } 6363 6364 if (queuedMouse !== null) { 6365 scheduleCallbackIfUnblocked(queuedMouse, unblocked); 6366 } 6367 6368 var unblock = function (queuedEvent) { 6369 return scheduleCallbackIfUnblocked(queuedEvent, unblocked); 6370 }; 6371 6372 queuedPointers.forEach(unblock); 6373 queuedPointerCaptures.forEach(unblock); 6374 6375 for (var _i = 0; _i < queuedExplicitHydrationTargets.length; _i++) { 6376 var queuedTarget = queuedExplicitHydrationTargets[_i]; 6377 6378 if (queuedTarget.blockedOn === unblocked) { 6379 queuedTarget.blockedOn = null; 6380 } 6381 } 6382 6383 while (queuedExplicitHydrationTargets.length > 0) { 6384 var nextExplicitTarget = queuedExplicitHydrationTargets[0]; 6385 6386 if (nextExplicitTarget.blockedOn !== null) { 6387 // We're still blocked. 6388 break; 6389 } else { 6390 attemptExplicitHydrationTarget(nextExplicitTarget); 6391 6392 if (nextExplicitTarget.blockedOn === null) { 6393 // We're unblocked. 6394 queuedExplicitHydrationTargets.shift(); 6395 } 6396 } 6397 } 6398 } 6399 6400 var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; // TODO: can we stop exporting these? 6401 6402 var _enabled = true; // This is exported in FB builds for use by legacy FB layer infra. 6403 // We'd like to remove this but it's not clear if this is safe. 6404 6405 function setEnabled(enabled) { 6406 _enabled = !!enabled; 6407 } 6408 function isEnabled() { 6409 return _enabled; 6410 } 6411 function createEventListenerWrapperWithPriority(targetContainer, domEventName, eventSystemFlags) { 6412 var eventPriority = getEventPriority(domEventName); 6413 var listenerWrapper; 6414 6415 switch (eventPriority) { 6416 case DiscreteEventPriority: 6417 listenerWrapper = dispatchDiscreteEvent; 6418 break; 6419 6420 case ContinuousEventPriority: 6421 listenerWrapper = dispatchContinuousEvent; 6422 break; 6423 6424 case DefaultEventPriority: 6425 default: 6426 listenerWrapper = dispatchEvent; 6427 break; 6428 } 6429 6430 return listenerWrapper.bind(null, domEventName, eventSystemFlags, targetContainer); 6431 } 6432 6433 function dispatchDiscreteEvent(domEventName, eventSystemFlags, container, nativeEvent) { 6434 var previousPriority = getCurrentUpdatePriority(); 6435 var prevTransition = ReactCurrentBatchConfig.transition; 6436 ReactCurrentBatchConfig.transition = null; 6437 6438 try { 6439 setCurrentUpdatePriority(DiscreteEventPriority); 6440 dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent); 6441 } finally { 6442 setCurrentUpdatePriority(previousPriority); 6443 ReactCurrentBatchConfig.transition = prevTransition; 6444 } 6445 } 6446 6447 function dispatchContinuousEvent(domEventName, eventSystemFlags, container, nativeEvent) { 6448 var previousPriority = getCurrentUpdatePriority(); 6449 var prevTransition = ReactCurrentBatchConfig.transition; 6450 ReactCurrentBatchConfig.transition = null; 6451 6452 try { 6453 setCurrentUpdatePriority(ContinuousEventPriority); 6454 dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent); 6455 } finally { 6456 setCurrentUpdatePriority(previousPriority); 6457 ReactCurrentBatchConfig.transition = prevTransition; 6458 } 6459 } 6460 6461 function dispatchEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6462 if (!_enabled) { 6463 return; 6464 } 6465 6466 { 6467 dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay(domEventName, eventSystemFlags, targetContainer, nativeEvent); 6468 } 6469 } 6470 6471 function dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay(domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6472 var blockedOn = findInstanceBlockingEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent); 6473 6474 if (blockedOn === null) { 6475 dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, return_targetInst, targetContainer); 6476 clearIfContinuousEvent(domEventName, nativeEvent); 6477 return; 6478 } 6479 6480 if (queueIfContinuousEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent)) { 6481 nativeEvent.stopPropagation(); 6482 return; 6483 } // We need to clear only if we didn't queue because 6484 // queueing is accumulative. 6485 6486 6487 clearIfContinuousEvent(domEventName, nativeEvent); 6488 6489 if (eventSystemFlags & IS_CAPTURE_PHASE && isDiscreteEventThatRequiresHydration(domEventName)) { 6490 while (blockedOn !== null) { 6491 var fiber = getInstanceFromNode(blockedOn); 6492 6493 if (fiber !== null) { 6494 attemptSynchronousHydration(fiber); 6495 } 6496 6497 var nextBlockedOn = findInstanceBlockingEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent); 6498 6499 if (nextBlockedOn === null) { 6500 dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, return_targetInst, targetContainer); 6501 } 6502 6503 if (nextBlockedOn === blockedOn) { 6504 break; 6505 } 6506 6507 blockedOn = nextBlockedOn; 6508 } 6509 6510 if (blockedOn !== null) { 6511 nativeEvent.stopPropagation(); 6512 } 6513 6514 return; 6515 } // This is not replayable so we'll invoke it but without a target, 6516 // in case the event system needs to trace it. 6517 6518 6519 dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, null, targetContainer); 6520 } 6521 6522 var return_targetInst = null; // Returns a SuspenseInstance or Container if it's blocked. 6523 // The return_targetInst field above is conceptually part of the return value. 6524 6525 function findInstanceBlockingEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6526 // TODO: Warn if _enabled is false. 6527 return_targetInst = null; 6528 var nativeEventTarget = getEventTarget(nativeEvent); 6529 var targetInst = getClosestInstanceFromNode(nativeEventTarget); 6530 6531 if (targetInst !== null) { 6532 var nearestMounted = getNearestMountedFiber(targetInst); 6533 6534 if (nearestMounted === null) { 6535 // This tree has been unmounted already. Dispatch without a target. 6536 targetInst = null; 6537 } else { 6538 var tag = nearestMounted.tag; 6539 6540 if (tag === SuspenseComponent) { 6541 var instance = getSuspenseInstanceFromFiber(nearestMounted); 6542 6543 if (instance !== null) { 6544 // Queue the event to be replayed later. Abort dispatching since we 6545 // don't want this event dispatched twice through the event system. 6546 // TODO: If this is the first discrete event in the queue. Schedule an increased 6547 // priority for this boundary. 6548 return instance; 6549 } // This shouldn't happen, something went wrong but to avoid blocking 6550 // the whole system, dispatch the event without a target. 6551 // TODO: Warn. 6552 6553 6554 targetInst = null; 6555 } else if (tag === HostRoot) { 6556 var root = nearestMounted.stateNode; 6557 6558 if (isRootDehydrated(root)) { 6559 // If this happens during a replay something went wrong and it might block 6560 // the whole system. 6561 return getContainerFromFiber(nearestMounted); 6562 } 6563 6564 targetInst = null; 6565 } else if (nearestMounted !== targetInst) { 6566 // If we get an event (ex: img onload) before committing that 6567 // component's mount, ignore it for now (that is, treat it as if it was an 6568 // event on a non-React tree). We might also consider queueing events and 6569 // dispatching them after the mount. 6570 targetInst = null; 6571 } 6572 } 6573 } 6574 6575 return_targetInst = targetInst; // We're not blocked on anything. 6576 6577 return null; 6578 } 6579 function getEventPriority(domEventName) { 6580 switch (domEventName) { 6581 // Used by SimpleEventPlugin: 6582 case 'cancel': 6583 case 'click': 6584 case 'close': 6585 case 'contextmenu': 6586 case 'copy': 6587 case 'cut': 6588 case 'auxclick': 6589 case 'dblclick': 6590 case 'dragend': 6591 case 'dragstart': 6592 case 'drop': 6593 case 'focusin': 6594 case 'focusout': 6595 case 'input': 6596 case 'invalid': 6597 case 'keydown': 6598 case 'keypress': 6599 case 'keyup': 6600 case 'mousedown': 6601 case 'mouseup': 6602 case 'paste': 6603 case 'pause': 6604 case 'play': 6605 case 'pointercancel': 6606 case 'pointerdown': 6607 case 'pointerup': 6608 case 'ratechange': 6609 case 'reset': 6610 case 'resize': 6611 case 'seeked': 6612 case 'submit': 6613 case 'touchcancel': 6614 case 'touchend': 6615 case 'touchstart': 6616 case 'volumechange': // Used by polyfills: 6617 // eslint-disable-next-line no-fallthrough 6618 6619 case 'change': 6620 case 'selectionchange': 6621 case 'textInput': 6622 case 'compositionstart': 6623 case 'compositionend': 6624 case 'compositionupdate': // Only enableCreateEventHandleAPI: 6625 // eslint-disable-next-line no-fallthrough 6626 6627 case 'beforeblur': 6628 case 'afterblur': // Not used by React but could be by user code: 6629 // eslint-disable-next-line no-fallthrough 6630 6631 case 'beforeinput': 6632 case 'blur': 6633 case 'fullscreenchange': 6634 case 'focus': 6635 case 'hashchange': 6636 case 'popstate': 6637 case 'select': 6638 case 'selectstart': 6639 return DiscreteEventPriority; 6640 6641 case 'drag': 6642 case 'dragenter': 6643 case 'dragexit': 6644 case 'dragleave': 6645 case 'dragover': 6646 case 'mousemove': 6647 case 'mouseout': 6648 case 'mouseover': 6649 case 'pointermove': 6650 case 'pointerout': 6651 case 'pointerover': 6652 case 'scroll': 6653 case 'toggle': 6654 case 'touchmove': 6655 case 'wheel': // Not used by React but could be by user code: 6656 // eslint-disable-next-line no-fallthrough 6657 6658 case 'mouseenter': 6659 case 'mouseleave': 6660 case 'pointerenter': 6661 case 'pointerleave': 6662 return ContinuousEventPriority; 6663 6664 case 'message': 6665 { 6666 // We might be in the Scheduler callback. 6667 // Eventually this mechanism will be replaced by a check 6668 // of the current priority on the native scheduler. 6669 var schedulerPriority = getCurrentPriorityLevel(); 6670 6671 switch (schedulerPriority) { 6672 case ImmediatePriority: 6673 return DiscreteEventPriority; 6674 6675 case UserBlockingPriority: 6676 return ContinuousEventPriority; 6677 6678 case NormalPriority: 6679 case LowPriority: 6680 // TODO: Handle LowSchedulerPriority, somehow. Maybe the same lane as hydration. 6681 return DefaultEventPriority; 6682 6683 case IdlePriority: 6684 return IdleEventPriority; 6685 6686 default: 6687 return DefaultEventPriority; 6688 } 6689 } 6690 6691 default: 6692 return DefaultEventPriority; 6693 } 6694 } 6695 6696 function addEventBubbleListener(target, eventType, listener) { 6697 target.addEventListener(eventType, listener, false); 6698 return listener; 6699 } 6700 function addEventCaptureListener(target, eventType, listener) { 6701 target.addEventListener(eventType, listener, true); 6702 return listener; 6703 } 6704 function addEventCaptureListenerWithPassiveFlag(target, eventType, listener, passive) { 6705 target.addEventListener(eventType, listener, { 6706 capture: true, 6707 passive: passive 6708 }); 6709 return listener; 6710 } 6711 function addEventBubbleListenerWithPassiveFlag(target, eventType, listener, passive) { 6712 target.addEventListener(eventType, listener, { 6713 passive: passive 6714 }); 6715 return listener; 6716 } 6717 6718 /** 6719 * These variables store information about text content of a target node, 6720 * allowing comparison of content before and after a given event. 6721 * 6722 * Identify the node where selection currently begins, then observe 6723 * both its text content and its current position in the DOM. Since the 6724 * browser may natively replace the target node during composition, we can 6725 * use its position to find its replacement. 6726 * 6727 * 6728 */ 6729 var root = null; 6730 var startText = null; 6731 var fallbackText = null; 6732 function initialize(nativeEventTarget) { 6733 root = nativeEventTarget; 6734 startText = getText(); 6735 return true; 6736 } 6737 function reset() { 6738 root = null; 6739 startText = null; 6740 fallbackText = null; 6741 } 6742 function getData() { 6743 if (fallbackText) { 6744 return fallbackText; 6745 } 6746 6747 var start; 6748 var startValue = startText; 6749 var startLength = startValue.length; 6750 var end; 6751 var endValue = getText(); 6752 var endLength = endValue.length; 6753 6754 for (start = 0; start < startLength; start++) { 6755 if (startValue[start] !== endValue[start]) { 6756 break; 6757 } 6758 } 6759 6760 var minEnd = startLength - start; 6761 6762 for (end = 1; end <= minEnd; end++) { 6763 if (startValue[startLength - end] !== endValue[endLength - end]) { 6764 break; 6765 } 6766 } 6767 6768 var sliceTail = end > 1 ? 1 - end : undefined; 6769 fallbackText = endValue.slice(start, sliceTail); 6770 return fallbackText; 6771 } 6772 function getText() { 6773 if ('value' in root) { 6774 return root.value; 6775 } 6776 6777 return root.textContent; 6778 } 6779 6780 /** 6781 * `charCode` represents the actual "character code" and is safe to use with 6782 * `String.fromCharCode`. As such, only keys that correspond to printable 6783 * characters produce a valid `charCode`, the only exception to this is Enter. 6784 * The Tab-key is considered non-printable and does not have a `charCode`, 6785 * presumably because it does not produce a tab-character in browsers. 6786 * 6787 * @param {object} nativeEvent Native browser event. 6788 * @return {number} Normalized `charCode` property. 6789 */ 6790 function getEventCharCode(nativeEvent) { 6791 var charCode; 6792 var keyCode = nativeEvent.keyCode; 6793 6794 if ('charCode' in nativeEvent) { 6795 charCode = nativeEvent.charCode; // FF does not set `charCode` for the Enter-key, check against `keyCode`. 6796 6797 if (charCode === 0 && keyCode === 13) { 6798 charCode = 13; 6799 } 6800 } else { 6801 // IE8 does not implement `charCode`, but `keyCode` has the correct value. 6802 charCode = keyCode; 6803 } // IE and Edge (on Windows) and Chrome / Safari (on Windows and Linux) 6804 // report Enter as charCode 10 when ctrl is pressed. 6805 6806 6807 if (charCode === 10) { 6808 charCode = 13; 6809 } // Some non-printable keys are reported in `charCode`/`keyCode`, discard them. 6810 // Must not discard the (non-)printable Enter-key. 6811 6812 6813 if (charCode >= 32 || charCode === 13) { 6814 return charCode; 6815 } 6816 6817 return 0; 6818 } 6819 6820 function functionThatReturnsTrue() { 6821 return true; 6822 } 6823 6824 function functionThatReturnsFalse() { 6825 return false; 6826 } // This is intentionally a factory so that we have different returned constructors. 6827 // If we had a single constructor, it would be megamorphic and engines would deopt. 6828 6829 6830 function createSyntheticEvent(Interface) { 6831 /** 6832 * Synthetic events are dispatched by event plugins, typically in response to a 6833 * top-level event delegation handler. 6834 * 6835 * These systems should generally use pooling to reduce the frequency of garbage 6836 * collection. The system should check `isPersistent` to determine whether the 6837 * event should be released into the pool after being dispatched. Users that 6838 * need a persisted event should invoke `persist`. 6839 * 6840 * Synthetic events (and subclasses) implement the DOM Level 3 Events API by 6841 * normalizing browser quirks. Subclasses do not necessarily have to implement a 6842 * DOM interface; custom application-specific events can also subclass this. 6843 */ 6844 function SyntheticBaseEvent(reactName, reactEventType, targetInst, nativeEvent, nativeEventTarget) { 6845 this._reactName = reactName; 6846 this._targetInst = targetInst; 6847 this.type = reactEventType; 6848 this.nativeEvent = nativeEvent; 6849 this.target = nativeEventTarget; 6850 this.currentTarget = null; 6851 6852 for (var _propName in Interface) { 6853 if (!Interface.hasOwnProperty(_propName)) { 6854 continue; 6855 } 6856 6857 var normalize = Interface[_propName]; 6858 6859 if (normalize) { 6860 this[_propName] = normalize(nativeEvent); 6861 } else { 6862 this[_propName] = nativeEvent[_propName]; 6863 } 6864 } 6865 6866 var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false; 6867 6868 if (defaultPrevented) { 6869 this.isDefaultPrevented = functionThatReturnsTrue; 6870 } else { 6871 this.isDefaultPrevented = functionThatReturnsFalse; 6872 } 6873 6874 this.isPropagationStopped = functionThatReturnsFalse; 6875 return this; 6876 } 6877 6878 assign(SyntheticBaseEvent.prototype, { 6879 preventDefault: function () { 6880 this.defaultPrevented = true; 6881 var event = this.nativeEvent; 6882 6883 if (!event) { 6884 return; 6885 } 6886 6887 if (event.preventDefault) { 6888 event.preventDefault(); // $FlowFixMe - flow is not aware of `unknown` in IE 6889 } else if (typeof event.returnValue !== 'unknown') { 6890 event.returnValue = false; 6891 } 6892 6893 this.isDefaultPrevented = functionThatReturnsTrue; 6894 }, 6895 stopPropagation: function () { 6896 var event = this.nativeEvent; 6897 6898 if (!event) { 6899 return; 6900 } 6901 6902 if (event.stopPropagation) { 6903 event.stopPropagation(); // $FlowFixMe - flow is not aware of `unknown` in IE 6904 } else if (typeof event.cancelBubble !== 'unknown') { 6905 // The ChangeEventPlugin registers a "propertychange" event for 6906 // IE. This event does not support bubbling or cancelling, and 6907 // any references to cancelBubble throw "Member not found". A 6908 // typeof check of "unknown" circumvents this issue (and is also 6909 // IE specific). 6910 event.cancelBubble = true; 6911 } 6912 6913 this.isPropagationStopped = functionThatReturnsTrue; 6914 }, 6915 6916 /** 6917 * We release all dispatched `SyntheticEvent`s after each event loop, adding 6918 * them back into the pool. This allows a way to hold onto a reference that 6919 * won't be added back into the pool. 6920 */ 6921 persist: function () {// Modern event system doesn't use pooling. 6922 }, 6923 6924 /** 6925 * Checks if this event should be released back into the pool. 6926 * 6927 * @return {boolean} True if this should not be released, false otherwise. 6928 */ 6929 isPersistent: functionThatReturnsTrue 6930 }); 6931 return SyntheticBaseEvent; 6932 } 6933 /** 6934 * @interface Event 6935 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 6936 */ 6937 6938 6939 var EventInterface = { 6940 eventPhase: 0, 6941 bubbles: 0, 6942 cancelable: 0, 6943 timeStamp: function (event) { 6944 return event.timeStamp || Date.now(); 6945 }, 6946 defaultPrevented: 0, 6947 isTrusted: 0 6948 }; 6949 var SyntheticEvent = createSyntheticEvent(EventInterface); 6950 6951 var UIEventInterface = assign({}, EventInterface, { 6952 view: 0, 6953 detail: 0 6954 }); 6955 6956 var SyntheticUIEvent = createSyntheticEvent(UIEventInterface); 6957 var lastMovementX; 6958 var lastMovementY; 6959 var lastMouseEvent; 6960 6961 function updateMouseMovementPolyfillState(event) { 6962 if (event !== lastMouseEvent) { 6963 if (lastMouseEvent && event.type === 'mousemove') { 6964 lastMovementX = event.screenX - lastMouseEvent.screenX; 6965 lastMovementY = event.screenY - lastMouseEvent.screenY; 6966 } else { 6967 lastMovementX = 0; 6968 lastMovementY = 0; 6969 } 6970 6971 lastMouseEvent = event; 6972 } 6973 } 6974 /** 6975 * @interface MouseEvent 6976 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 6977 */ 6978 6979 6980 var MouseEventInterface = assign({}, UIEventInterface, { 6981 screenX: 0, 6982 screenY: 0, 6983 clientX: 0, 6984 clientY: 0, 6985 pageX: 0, 6986 pageY: 0, 6987 ctrlKey: 0, 6988 shiftKey: 0, 6989 altKey: 0, 6990 metaKey: 0, 6991 getModifierState: getEventModifierState, 6992 button: 0, 6993 buttons: 0, 6994 relatedTarget: function (event) { 6995 if (event.relatedTarget === undefined) return event.fromElement === event.srcElement ? event.toElement : event.fromElement; 6996 return event.relatedTarget; 6997 }, 6998 movementX: function (event) { 6999 if ('movementX' in event) { 7000 return event.movementX; 7001 } 7002 7003 updateMouseMovementPolyfillState(event); 7004 return lastMovementX; 7005 }, 7006 movementY: function (event) { 7007 if ('movementY' in event) { 7008 return event.movementY; 7009 } // Don't need to call updateMouseMovementPolyfillState() here 7010 // because it's guaranteed to have already run when movementX 7011 // was copied. 7012 7013 7014 return lastMovementY; 7015 } 7016 }); 7017 7018 var SyntheticMouseEvent = createSyntheticEvent(MouseEventInterface); 7019 /** 7020 * @interface DragEvent 7021 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 7022 */ 7023 7024 var DragEventInterface = assign({}, MouseEventInterface, { 7025 dataTransfer: 0 7026 }); 7027 7028 var SyntheticDragEvent = createSyntheticEvent(DragEventInterface); 7029 /** 7030 * @interface FocusEvent 7031 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 7032 */ 7033 7034 var FocusEventInterface = assign({}, UIEventInterface, { 7035 relatedTarget: 0 7036 }); 7037 7038 var SyntheticFocusEvent = createSyntheticEvent(FocusEventInterface); 7039 /** 7040 * @interface Event 7041 * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface 7042 * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent 7043 */ 7044 7045 var AnimationEventInterface = assign({}, EventInterface, { 7046 animationName: 0, 7047 elapsedTime: 0, 7048 pseudoElement: 0 7049 }); 7050 7051 var SyntheticAnimationEvent = createSyntheticEvent(AnimationEventInterface); 7052 /** 7053 * @interface Event 7054 * @see http://www.w3.org/TR/clipboard-apis/ 7055 */ 7056 7057 var ClipboardEventInterface = assign({}, EventInterface, { 7058 clipboardData: function (event) { 7059 return 'clipboardData' in event ? event.clipboardData : window.clipboardData; 7060 } 7061 }); 7062 7063 var SyntheticClipboardEvent = createSyntheticEvent(ClipboardEventInterface); 7064 /** 7065 * @interface Event 7066 * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents 7067 */ 7068 7069 var CompositionEventInterface = assign({}, EventInterface, { 7070 data: 0 7071 }); 7072 7073 var SyntheticCompositionEvent = createSyntheticEvent(CompositionEventInterface); 7074 /** 7075 * @interface Event 7076 * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105 7077 * /#events-inputevents 7078 */ 7079 // Happens to share the same list for now. 7080 7081 var SyntheticInputEvent = SyntheticCompositionEvent; 7082 /** 7083 * Normalization of deprecated HTML5 `key` values 7084 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names 7085 */ 7086 7087 var normalizeKey = { 7088 Esc: 'Escape', 7089 Spacebar: ' ', 7090 Left: 'ArrowLeft', 7091 Up: 'ArrowUp', 7092 Right: 'ArrowRight', 7093 Down: 'ArrowDown', 7094 Del: 'Delete', 7095 Win: 'OS', 7096 Menu: 'ContextMenu', 7097 Apps: 'ContextMenu', 7098 Scroll: 'ScrollLock', 7099 MozPrintableKey: 'Unidentified' 7100 }; 7101 /** 7102 * Translation from legacy `keyCode` to HTML5 `key` 7103 * Only special keys supported, all others depend on keyboard layout or browser 7104 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names 7105 */ 7106 7107 var translateToKey = { 7108 '8': 'Backspace', 7109 '9': 'Tab', 7110 '12': 'Clear', 7111 '13': 'Enter', 7112 '16': 'Shift', 7113 '17': 'Control', 7114 '18': 'Alt', 7115 '19': 'Pause', 7116 '20': 'CapsLock', 7117 '27': 'Escape', 7118 '32': ' ', 7119 '33': 'PageUp', 7120 '34': 'PageDown', 7121 '35': 'End', 7122 '36': 'Home', 7123 '37': 'ArrowLeft', 7124 '38': 'ArrowUp', 7125 '39': 'ArrowRight', 7126 '40': 'ArrowDown', 7127 '45': 'Insert', 7128 '46': 'Delete', 7129 '112': 'F1', 7130 '113': 'F2', 7131 '114': 'F3', 7132 '115': 'F4', 7133 '116': 'F5', 7134 '117': 'F6', 7135 '118': 'F7', 7136 '119': 'F8', 7137 '120': 'F9', 7138 '121': 'F10', 7139 '122': 'F11', 7140 '123': 'F12', 7141 '144': 'NumLock', 7142 '145': 'ScrollLock', 7143 '224': 'Meta' 7144 }; 7145 /** 7146 * @param {object} nativeEvent Native browser event. 7147 * @return {string} Normalized `key` property. 7148 */ 7149 7150 function getEventKey(nativeEvent) { 7151 if (nativeEvent.key) { 7152 // Normalize inconsistent values reported by browsers due to 7153 // implementations of a working draft specification. 7154 // FireFox implements `key` but returns `MozPrintableKey` for all 7155 // printable characters (normalized to `Unidentified`), ignore it. 7156 var key = normalizeKey[nativeEvent.key] || nativeEvent.key; 7157 7158 if (key !== 'Unidentified') { 7159 return key; 7160 } 7161 } // Browser does not implement `key`, polyfill as much of it as we can. 7162 7163 7164 if (nativeEvent.type === 'keypress') { 7165 var charCode = getEventCharCode(nativeEvent); // The enter-key is technically both printable and non-printable and can 7166 // thus be captured by `keypress`, no other non-printable key should. 7167 7168 return charCode === 13 ? 'Enter' : String.fromCharCode(charCode); 7169 } 7170 7171 if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') { 7172 // While user keyboard layout determines the actual meaning of each 7173 // `keyCode` value, almost all function keys have a universal value. 7174 return translateToKey[nativeEvent.keyCode] || 'Unidentified'; 7175 } 7176 7177 return ''; 7178 } 7179 /** 7180 * Translation from modifier key to the associated property in the event. 7181 * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers 7182 */ 7183 7184 7185 var modifierKeyToProp = { 7186 Alt: 'altKey', 7187 Control: 'ctrlKey', 7188 Meta: 'metaKey', 7189 Shift: 'shiftKey' 7190 }; // Older browsers (Safari <= 10, iOS Safari <= 10.2) do not support 7191 // getModifierState. If getModifierState is not supported, we map it to a set of 7192 // modifier keys exposed by the event. In this case, Lock-keys are not supported. 7193 7194 function modifierStateGetter(keyArg) { 7195 var syntheticEvent = this; 7196 var nativeEvent = syntheticEvent.nativeEvent; 7197 7198 if (nativeEvent.getModifierState) { 7199 return nativeEvent.getModifierState(keyArg); 7200 } 7201 7202 var keyProp = modifierKeyToProp[keyArg]; 7203 return keyProp ? !!nativeEvent[keyProp] : false; 7204 } 7205 7206 function getEventModifierState(nativeEvent) { 7207 return modifierStateGetter; 7208 } 7209 /** 7210 * @interface KeyboardEvent 7211 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 7212 */ 7213 7214 7215 var KeyboardEventInterface = assign({}, UIEventInterface, { 7216 key: getEventKey, 7217 code: 0, 7218 location: 0, 7219 ctrlKey: 0, 7220 shiftKey: 0, 7221 altKey: 0, 7222 metaKey: 0, 7223 repeat: 0, 7224 locale: 0, 7225 getModifierState: getEventModifierState, 7226 // Legacy Interface 7227 charCode: function (event) { 7228 // `charCode` is the result of a KeyPress event and represents the value of 7229 // the actual printable character. 7230 // KeyPress is deprecated, but its replacement is not yet final and not 7231 // implemented in any major browser. Only KeyPress has charCode. 7232 if (event.type === 'keypress') { 7233 return getEventCharCode(event); 7234 } 7235 7236 return 0; 7237 }, 7238 keyCode: function (event) { 7239 // `keyCode` is the result of a KeyDown/Up event and represents the value of 7240 // physical keyboard key. 7241 // The actual meaning of the value depends on the users' keyboard layout 7242 // which cannot be detected. Assuming that it is a US keyboard layout 7243 // provides a surprisingly accurate mapping for US and European users. 7244 // Due to this, it is left to the user to implement at this time. 7245 if (event.type === 'keydown' || event.type === 'keyup') { 7246 return event.keyCode; 7247 } 7248 7249 return 0; 7250 }, 7251 which: function (event) { 7252 // `which` is an alias for either `keyCode` or `charCode` depending on the 7253 // type of the event. 7254 if (event.type === 'keypress') { 7255 return getEventCharCode(event); 7256 } 7257 7258 if (event.type === 'keydown' || event.type === 'keyup') { 7259 return event.keyCode; 7260 } 7261 7262 return 0; 7263 } 7264 }); 7265 7266 var SyntheticKeyboardEvent = createSyntheticEvent(KeyboardEventInterface); 7267 /** 7268 * @interface PointerEvent 7269 * @see http://www.w3.org/TR/pointerevents/ 7270 */ 7271 7272 var PointerEventInterface = assign({}, MouseEventInterface, { 7273 pointerId: 0, 7274 width: 0, 7275 height: 0, 7276 pressure: 0, 7277 tangentialPressure: 0, 7278 tiltX: 0, 7279 tiltY: 0, 7280 twist: 0, 7281 pointerType: 0, 7282 isPrimary: 0 7283 }); 7284 7285 var SyntheticPointerEvent = createSyntheticEvent(PointerEventInterface); 7286 /** 7287 * @interface TouchEvent 7288 * @see http://www.w3.org/TR/touch-events/ 7289 */ 7290 7291 var TouchEventInterface = assign({}, UIEventInterface, { 7292 touches: 0, 7293 targetTouches: 0, 7294 changedTouches: 0, 7295 altKey: 0, 7296 metaKey: 0, 7297 ctrlKey: 0, 7298 shiftKey: 0, 7299 getModifierState: getEventModifierState 7300 }); 7301 7302 var SyntheticTouchEvent = createSyntheticEvent(TouchEventInterface); 7303 /** 7304 * @interface Event 7305 * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events- 7306 * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent 7307 */ 7308 7309 var TransitionEventInterface = assign({}, EventInterface, { 7310 propertyName: 0, 7311 elapsedTime: 0, 7312 pseudoElement: 0 7313 }); 7314 7315 var SyntheticTransitionEvent = createSyntheticEvent(TransitionEventInterface); 7316 /** 7317 * @interface WheelEvent 7318 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 7319 */ 7320 7321 var WheelEventInterface = assign({}, MouseEventInterface, { 7322 deltaX: function (event) { 7323 return 'deltaX' in event ? event.deltaX : // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive). 7324 'wheelDeltaX' in event ? -event.wheelDeltaX : 0; 7325 }, 7326 deltaY: function (event) { 7327 return 'deltaY' in event ? event.deltaY : // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive). 7328 'wheelDeltaY' in event ? -event.wheelDeltaY : // Fallback to `wheelDelta` for IE<9 and normalize (down is positive). 7329 'wheelDelta' in event ? -event.wheelDelta : 0; 7330 }, 7331 deltaZ: 0, 7332 // Browsers without "deltaMode" is reporting in raw wheel delta where one 7333 // notch on the scroll is always +/- 120, roughly equivalent to pixels. 7334 // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or 7335 // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size. 7336 deltaMode: 0 7337 }); 7338 7339 var SyntheticWheelEvent = createSyntheticEvent(WheelEventInterface); 7340 7341 var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space 7342 7343 var START_KEYCODE = 229; 7344 var canUseCompositionEvent = canUseDOM && 'CompositionEvent' in window; 7345 var documentMode = null; 7346 7347 if (canUseDOM && 'documentMode' in document) { 7348 documentMode = document.documentMode; 7349 } // Webkit offers a very useful `textInput` event that can be used to 7350 // directly represent `beforeInput`. The IE `textinput` event is not as 7351 // useful, so we don't use it. 7352 7353 7354 var canUseTextInputEvent = canUseDOM && 'TextEvent' in window && !documentMode; // In IE9+, we have access to composition events, but the data supplied 7355 // by the native compositionend event may be incorrect. Japanese ideographic 7356 // spaces, for instance (\u3000) are not recorded correctly. 7357 7358 var useFallbackCompositionData = canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11); 7359 var SPACEBAR_CODE = 32; 7360 var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE); 7361 7362 function registerEvents() { 7363 registerTwoPhaseEvent('onBeforeInput', ['compositionend', 'keypress', 'textInput', 'paste']); 7364 registerTwoPhaseEvent('onCompositionEnd', ['compositionend', 'focusout', 'keydown', 'keypress', 'keyup', 'mousedown']); 7365 registerTwoPhaseEvent('onCompositionStart', ['compositionstart', 'focusout', 'keydown', 'keypress', 'keyup', 'mousedown']); 7366 registerTwoPhaseEvent('onCompositionUpdate', ['compositionupdate', 'focusout', 'keydown', 'keypress', 'keyup', 'mousedown']); 7367 } // Track whether we've ever handled a keypress on the space key. 7368 7369 7370 var hasSpaceKeypress = false; 7371 /** 7372 * Return whether a native keypress event is assumed to be a command. 7373 * This is required because Firefox fires `keypress` events for key commands 7374 * (cut, copy, select-all, etc.) even though no character is inserted. 7375 */ 7376 7377 function isKeypressCommand(nativeEvent) { 7378 return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) && // ctrlKey && altKey is equivalent to AltGr, and is not a command. 7379 !(nativeEvent.ctrlKey && nativeEvent.altKey); 7380 } 7381 /** 7382 * Translate native top level events into event types. 7383 */ 7384 7385 7386 function getCompositionEventType(domEventName) { 7387 switch (domEventName) { 7388 case 'compositionstart': 7389 return 'onCompositionStart'; 7390 7391 case 'compositionend': 7392 return 'onCompositionEnd'; 7393 7394 case 'compositionupdate': 7395 return 'onCompositionUpdate'; 7396 } 7397 } 7398 /** 7399 * Does our fallback best-guess model think this event signifies that 7400 * composition has begun? 7401 */ 7402 7403 7404 function isFallbackCompositionStart(domEventName, nativeEvent) { 7405 return domEventName === 'keydown' && nativeEvent.keyCode === START_KEYCODE; 7406 } 7407 /** 7408 * Does our fallback mode think that this event is the end of composition? 7409 */ 7410 7411 7412 function isFallbackCompositionEnd(domEventName, nativeEvent) { 7413 switch (domEventName) { 7414 case 'keyup': 7415 // Command keys insert or clear IME input. 7416 return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1; 7417 7418 case 'keydown': 7419 // Expect IME keyCode on each keydown. If we get any other 7420 // code we must have exited earlier. 7421 return nativeEvent.keyCode !== START_KEYCODE; 7422 7423 case 'keypress': 7424 case 'mousedown': 7425 case 'focusout': 7426 // Events are not possible without cancelling IME. 7427 return true; 7428 7429 default: 7430 return false; 7431 } 7432 } 7433 /** 7434 * Google Input Tools provides composition data via a CustomEvent, 7435 * with the `data` property populated in the `detail` object. If this 7436 * is available on the event object, use it. If not, this is a plain 7437 * composition event and we have nothing special to extract. 7438 * 7439 * @param {object} nativeEvent 7440 * @return {?string} 7441 */ 7442 7443 7444 function getDataFromCustomEvent(nativeEvent) { 7445 var detail = nativeEvent.detail; 7446 7447 if (typeof detail === 'object' && 'data' in detail) { 7448 return detail.data; 7449 } 7450 7451 return null; 7452 } 7453 /** 7454 * Check if a composition event was triggered by Korean IME. 7455 * Our fallback mode does not work well with IE's Korean IME, 7456 * so just use native composition events when Korean IME is used. 7457 * Although CompositionEvent.locale property is deprecated, 7458 * it is available in IE, where our fallback mode is enabled. 7459 * 7460 * @param {object} nativeEvent 7461 * @return {boolean} 7462 */ 7463 7464 7465 function isUsingKoreanIME(nativeEvent) { 7466 return nativeEvent.locale === 'ko'; 7467 } // Track the current IME composition status, if any. 7468 7469 7470 var isComposing = false; 7471 /** 7472 * @return {?object} A SyntheticCompositionEvent. 7473 */ 7474 7475 function extractCompositionEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget) { 7476 var eventType; 7477 var fallbackData; 7478 7479 if (canUseCompositionEvent) { 7480 eventType = getCompositionEventType(domEventName); 7481 } else if (!isComposing) { 7482 if (isFallbackCompositionStart(domEventName, nativeEvent)) { 7483 eventType = 'onCompositionStart'; 7484 } 7485 } else if (isFallbackCompositionEnd(domEventName, nativeEvent)) { 7486 eventType = 'onCompositionEnd'; 7487 } 7488 7489 if (!eventType) { 7490 return null; 7491 } 7492 7493 if (useFallbackCompositionData && !isUsingKoreanIME(nativeEvent)) { 7494 // The current composition is stored statically and must not be 7495 // overwritten while composition continues. 7496 if (!isComposing && eventType === 'onCompositionStart') { 7497 isComposing = initialize(nativeEventTarget); 7498 } else if (eventType === 'onCompositionEnd') { 7499 if (isComposing) { 7500 fallbackData = getData(); 7501 } 7502 } 7503 } 7504 7505 var listeners = accumulateTwoPhaseListeners(targetInst, eventType); 7506 7507 if (listeners.length > 0) { 7508 var event = new SyntheticCompositionEvent(eventType, domEventName, null, nativeEvent, nativeEventTarget); 7509 dispatchQueue.push({ 7510 event: event, 7511 listeners: listeners 7512 }); 7513 7514 if (fallbackData) { 7515 // Inject data generated from fallback path into the synthetic event. 7516 // This matches the property of native CompositionEventInterface. 7517 event.data = fallbackData; 7518 } else { 7519 var customData = getDataFromCustomEvent(nativeEvent); 7520 7521 if (customData !== null) { 7522 event.data = customData; 7523 } 7524 } 7525 } 7526 } 7527 7528 function getNativeBeforeInputChars(domEventName, nativeEvent) { 7529 switch (domEventName) { 7530 case 'compositionend': 7531 return getDataFromCustomEvent(nativeEvent); 7532 7533 case 'keypress': 7534 /** 7535 * If native `textInput` events are available, our goal is to make 7536 * use of them. However, there is a special case: the spacebar key. 7537 * In Webkit, preventing default on a spacebar `textInput` event 7538 * cancels character insertion, but it *also* causes the browser 7539 * to fall back to its default spacebar behavior of scrolling the 7540 * page. 7541 * 7542 * Tracking at: 7543 * https://code.google.com/p/chromium/issues/detail?id=355103 7544 * 7545 * To avoid this issue, use the keypress event as if no `textInput` 7546 * event is available. 7547 */ 7548 var which = nativeEvent.which; 7549 7550 if (which !== SPACEBAR_CODE) { 7551 return null; 7552 } 7553 7554 hasSpaceKeypress = true; 7555 return SPACEBAR_CHAR; 7556 7557 case 'textInput': 7558 // Record the characters to be added to the DOM. 7559 var chars = nativeEvent.data; // If it's a spacebar character, assume that we have already handled 7560 // it at the keypress level and bail immediately. Android Chrome 7561 // doesn't give us keycodes, so we need to ignore it. 7562 7563 if (chars === SPACEBAR_CHAR && hasSpaceKeypress) { 7564 return null; 7565 } 7566 7567 return chars; 7568 7569 default: 7570 // For other native event types, do nothing. 7571 return null; 7572 } 7573 } 7574 /** 7575 * For browsers that do not provide the `textInput` event, extract the 7576 * appropriate string to use for SyntheticInputEvent. 7577 */ 7578 7579 7580 function getFallbackBeforeInputChars(domEventName, nativeEvent) { 7581 // If we are currently composing (IME) and using a fallback to do so, 7582 // try to extract the composed characters from the fallback object. 7583 // If composition event is available, we extract a string only at 7584 // compositionevent, otherwise extract it at fallback events. 7585 if (isComposing) { 7586 if (domEventName === 'compositionend' || !canUseCompositionEvent && isFallbackCompositionEnd(domEventName, nativeEvent)) { 7587 var chars = getData(); 7588 reset(); 7589 isComposing = false; 7590 return chars; 7591 } 7592 7593 return null; 7594 } 7595 7596 switch (domEventName) { 7597 case 'paste': 7598 // If a paste event occurs after a keypress, throw out the input 7599 // chars. Paste events should not lead to BeforeInput events. 7600 return null; 7601 7602 case 'keypress': 7603 /** 7604 * As of v27, Firefox may fire keypress events even when no character 7605 * will be inserted. A few possibilities: 7606 * 7607 * - `which` is `0`. Arrow keys, Esc key, etc. 7608 * 7609 * - `which` is the pressed key code, but no char is available. 7610 * Ex: 'AltGr + d` in Polish. There is no modified character for 7611 * this key combination and no character is inserted into the 7612 * document, but FF fires the keypress for char code `100` anyway. 7613 * No `input` event will occur. 7614 * 7615 * - `which` is the pressed key code, but a command combination is 7616 * being used. Ex: `Cmd+C`. No character is inserted, and no 7617 * `input` event will occur. 7618 */ 7619 if (!isKeypressCommand(nativeEvent)) { 7620 // IE fires the `keypress` event when a user types an emoji via 7621 // Touch keyboard of Windows. In such a case, the `char` property 7622 // holds an emoji character like `\uD83D\uDE0A`. Because its length 7623 // is 2, the property `which` does not represent an emoji correctly. 7624 // In such a case, we directly return the `char` property instead of 7625 // using `which`. 7626 if (nativeEvent.char && nativeEvent.char.length > 1) { 7627 return nativeEvent.char; 7628 } else if (nativeEvent.which) { 7629 return String.fromCharCode(nativeEvent.which); 7630 } 7631 } 7632 7633 return null; 7634 7635 case 'compositionend': 7636 return useFallbackCompositionData && !isUsingKoreanIME(nativeEvent) ? null : nativeEvent.data; 7637 7638 default: 7639 return null; 7640 } 7641 } 7642 /** 7643 * Extract a SyntheticInputEvent for `beforeInput`, based on either native 7644 * `textInput` or fallback behavior. 7645 * 7646 * @return {?object} A SyntheticInputEvent. 7647 */ 7648 7649 7650 function extractBeforeInputEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget) { 7651 var chars; 7652 7653 if (canUseTextInputEvent) { 7654 chars = getNativeBeforeInputChars(domEventName, nativeEvent); 7655 } else { 7656 chars = getFallbackBeforeInputChars(domEventName, nativeEvent); 7657 } // If no characters are being inserted, no BeforeInput event should 7658 // be fired. 7659 7660 7661 if (!chars) { 7662 return null; 7663 } 7664 7665 var listeners = accumulateTwoPhaseListeners(targetInst, 'onBeforeInput'); 7666 7667 if (listeners.length > 0) { 7668 var event = new SyntheticInputEvent('onBeforeInput', 'beforeinput', null, nativeEvent, nativeEventTarget); 7669 dispatchQueue.push({ 7670 event: event, 7671 listeners: listeners 7672 }); 7673 event.data = chars; 7674 } 7675 } 7676 /** 7677 * Create an `onBeforeInput` event to match 7678 * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents. 7679 * 7680 * This event plugin is based on the native `textInput` event 7681 * available in Chrome, Safari, Opera, and IE. This event fires after 7682 * `onKeyPress` and `onCompositionEnd`, but before `onInput`. 7683 * 7684 * `beforeInput` is spec'd but not implemented in any browsers, and 7685 * the `input` event does not provide any useful information about what has 7686 * actually been added, contrary to the spec. Thus, `textInput` is the best 7687 * available event to identify the characters that have actually been inserted 7688 * into the target node. 7689 * 7690 * This plugin is also responsible for emitting `composition` events, thus 7691 * allowing us to share composition fallback code for both `beforeInput` and 7692 * `composition` event types. 7693 */ 7694 7695 7696 function extractEvents(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 7697 extractCompositionEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget); 7698 extractBeforeInputEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget); 7699 } 7700 7701 /** 7702 * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary 7703 */ 7704 var supportedInputTypes = { 7705 color: true, 7706 date: true, 7707 datetime: true, 7708 'datetime-local': true, 7709 email: true, 7710 month: true, 7711 number: true, 7712 password: true, 7713 range: true, 7714 search: true, 7715 tel: true, 7716 text: true, 7717 time: true, 7718 url: true, 7719 week: true 7720 }; 7721 7722 function isTextInputElement(elem) { 7723 var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase(); 7724 7725 if (nodeName === 'input') { 7726 return !!supportedInputTypes[elem.type]; 7727 } 7728 7729 if (nodeName === 'textarea') { 7730 return true; 7731 } 7732 7733 return false; 7734 } 7735 7736 /** 7737 * Checks if an event is supported in the current execution environment. 7738 * 7739 * NOTE: This will not work correctly for non-generic events such as `change`, 7740 * `reset`, `load`, `error`, and `select`. 7741 * 7742 * Borrows from Modernizr. 7743 * 7744 * @param {string} eventNameSuffix Event name, e.g. "click". 7745 * @return {boolean} True if the event is supported. 7746 * @internal 7747 * @license Modernizr 3.0.0pre (Custom Build) | MIT 7748 */ 7749 7750 function isEventSupported(eventNameSuffix) { 7751 if (!canUseDOM) { 7752 return false; 7753 } 7754 7755 var eventName = 'on' + eventNameSuffix; 7756 var isSupported = (eventName in document); 7757 7758 if (!isSupported) { 7759 var element = document.createElement('div'); 7760 element.setAttribute(eventName, 'return;'); 7761 isSupported = typeof element[eventName] === 'function'; 7762 } 7763 7764 return isSupported; 7765 } 7766 7767 function registerEvents$1() { 7768 registerTwoPhaseEvent('onChange', ['change', 'click', 'focusin', 'focusout', 'input', 'keydown', 'keyup', 'selectionchange']); 7769 } 7770 7771 function createAndAccumulateChangeEvent(dispatchQueue, inst, nativeEvent, target) { 7772 // Flag this event loop as needing state restore. 7773 enqueueStateRestore(target); 7774 var listeners = accumulateTwoPhaseListeners(inst, 'onChange'); 7775 7776 if (listeners.length > 0) { 7777 var event = new SyntheticEvent('onChange', 'change', null, nativeEvent, target); 7778 dispatchQueue.push({ 7779 event: event, 7780 listeners: listeners 7781 }); 7782 } 7783 } 7784 /** 7785 * For IE shims 7786 */ 7787 7788 7789 var activeElement = null; 7790 var activeElementInst = null; 7791 /** 7792 * SECTION: handle `change` event 7793 */ 7794 7795 function shouldUseChangeEvent(elem) { 7796 var nodeName = elem.nodeName && elem.nodeName.toLowerCase(); 7797 return nodeName === 'select' || nodeName === 'input' && elem.type === 'file'; 7798 } 7799 7800 function manualDispatchChangeEvent(nativeEvent) { 7801 var dispatchQueue = []; 7802 createAndAccumulateChangeEvent(dispatchQueue, activeElementInst, nativeEvent, getEventTarget(nativeEvent)); // If change and propertychange bubbled, we'd just bind to it like all the 7803 // other events and have it go through ReactBrowserEventEmitter. Since it 7804 // doesn't, we manually listen for the events and so we have to enqueue and 7805 // process the abstract event manually. 7806 // 7807 // Batching is necessary here in order to ensure that all event handlers run 7808 // before the next rerender (including event handlers attached to ancestor 7809 // elements instead of directly on the input). Without this, controlled 7810 // components don't work properly in conjunction with event bubbling because 7811 // the component is rerendered and the value reverted before all the event 7812 // handlers can run. See https://github.com/facebook/react/issues/708. 7813 7814 batchedUpdates(runEventInBatch, dispatchQueue); 7815 } 7816 7817 function runEventInBatch(dispatchQueue) { 7818 processDispatchQueue(dispatchQueue, 0); 7819 } 7820 7821 function getInstIfValueChanged(targetInst) { 7822 var targetNode = getNodeFromInstance(targetInst); 7823 7824 if (updateValueIfChanged(targetNode)) { 7825 return targetInst; 7826 } 7827 } 7828 7829 function getTargetInstForChangeEvent(domEventName, targetInst) { 7830 if (domEventName === 'change') { 7831 return targetInst; 7832 } 7833 } 7834 /** 7835 * SECTION: handle `input` event 7836 */ 7837 7838 7839 var isInputEventSupported = false; 7840 7841 if (canUseDOM) { 7842 // IE9 claims to support the input event but fails to trigger it when 7843 // deleting text, so we ignore its input events. 7844 isInputEventSupported = isEventSupported('input') && (!document.documentMode || document.documentMode > 9); 7845 } 7846 /** 7847 * (For IE <=9) Starts tracking propertychange events on the passed-in element 7848 * and override the value property so that we can distinguish user events from 7849 * value changes in JS. 7850 */ 7851 7852 7853 function startWatchingForValueChange(target, targetInst) { 7854 activeElement = target; 7855 activeElementInst = targetInst; 7856 activeElement.attachEvent('onpropertychange', handlePropertyChange); 7857 } 7858 /** 7859 * (For IE <=9) Removes the event listeners from the currently-tracked element, 7860 * if any exists. 7861 */ 7862 7863 7864 function stopWatchingForValueChange() { 7865 if (!activeElement) { 7866 return; 7867 } 7868 7869 activeElement.detachEvent('onpropertychange', handlePropertyChange); 7870 activeElement = null; 7871 activeElementInst = null; 7872 } 7873 /** 7874 * (For IE <=9) Handles a propertychange event, sending a `change` event if 7875 * the value of the active element has changed. 7876 */ 7877 7878 7879 function handlePropertyChange(nativeEvent) { 7880 if (nativeEvent.propertyName !== 'value') { 7881 return; 7882 } 7883 7884 if (getInstIfValueChanged(activeElementInst)) { 7885 manualDispatchChangeEvent(nativeEvent); 7886 } 7887 } 7888 7889 function handleEventsForInputEventPolyfill(domEventName, target, targetInst) { 7890 if (domEventName === 'focusin') { 7891 // In IE9, propertychange fires for most input events but is buggy and 7892 // doesn't fire when text is deleted, but conveniently, selectionchange 7893 // appears to fire in all of the remaining cases so we catch those and 7894 // forward the event if the value has changed 7895 // In either case, we don't want to call the event handler if the value 7896 // is changed from JS so we redefine a setter for `.value` that updates 7897 // our activeElementValue variable, allowing us to ignore those changes 7898 // 7899 // stopWatching() should be a noop here but we call it just in case we 7900 // missed a blur event somehow. 7901 stopWatchingForValueChange(); 7902 startWatchingForValueChange(target, targetInst); 7903 } else if (domEventName === 'focusout') { 7904 stopWatchingForValueChange(); 7905 } 7906 } // For IE8 and IE9. 7907 7908 7909 function getTargetInstForInputEventPolyfill(domEventName, targetInst) { 7910 if (domEventName === 'selectionchange' || domEventName === 'keyup' || domEventName === 'keydown') { 7911 // On the selectionchange event, the target is just document which isn't 7912 // helpful for us so just check activeElement instead. 7913 // 7914 // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire 7915 // propertychange on the first input event after setting `value` from a 7916 // script and fires only keydown, keypress, keyup. Catching keyup usually 7917 // gets it and catching keydown lets us fire an event for the first 7918 // keystroke if user does a key repeat (it'll be a little delayed: right 7919 // before the second keystroke). Other input methods (e.g., paste) seem to 7920 // fire selectionchange normally. 7921 return getInstIfValueChanged(activeElementInst); 7922 } 7923 } 7924 /** 7925 * SECTION: handle `click` event 7926 */ 7927 7928 7929 function shouldUseClickEvent(elem) { 7930 // Use the `click` event to detect changes to checkbox and radio inputs. 7931 // This approach works across all browsers, whereas `change` does not fire 7932 // until `blur` in IE8. 7933 var nodeName = elem.nodeName; 7934 return nodeName && nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio'); 7935 } 7936 7937 function getTargetInstForClickEvent(domEventName, targetInst) { 7938 if (domEventName === 'click') { 7939 return getInstIfValueChanged(targetInst); 7940 } 7941 } 7942 7943 function getTargetInstForInputOrChangeEvent(domEventName, targetInst) { 7944 if (domEventName === 'input' || domEventName === 'change') { 7945 return getInstIfValueChanged(targetInst); 7946 } 7947 } 7948 7949 function handleControlledInputBlur(node) { 7950 var state = node._wrapperState; 7951 7952 if (!state || !state.controlled || node.type !== 'number') { 7953 return; 7954 } 7955 7956 { 7957 // If controlled, assign the value attribute to the current value on blur 7958 setDefaultValue(node, 'number', node.value); 7959 } 7960 } 7961 /** 7962 * This plugin creates an `onChange` event that normalizes change events 7963 * across form elements. This event fires at a time when it's possible to 7964 * change the element's value without seeing a flicker. 7965 * 7966 * Supported elements are: 7967 * - input (see `isTextInputElement`) 7968 * - textarea 7969 * - select 7970 */ 7971 7972 7973 function extractEvents$1(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 7974 var targetNode = targetInst ? getNodeFromInstance(targetInst) : window; 7975 var getTargetInstFunc, handleEventFunc; 7976 7977 if (shouldUseChangeEvent(targetNode)) { 7978 getTargetInstFunc = getTargetInstForChangeEvent; 7979 } else if (isTextInputElement(targetNode)) { 7980 if (isInputEventSupported) { 7981 getTargetInstFunc = getTargetInstForInputOrChangeEvent; 7982 } else { 7983 getTargetInstFunc = getTargetInstForInputEventPolyfill; 7984 handleEventFunc = handleEventsForInputEventPolyfill; 7985 } 7986 } else if (shouldUseClickEvent(targetNode)) { 7987 getTargetInstFunc = getTargetInstForClickEvent; 7988 } 7989 7990 if (getTargetInstFunc) { 7991 var inst = getTargetInstFunc(domEventName, targetInst); 7992 7993 if (inst) { 7994 createAndAccumulateChangeEvent(dispatchQueue, inst, nativeEvent, nativeEventTarget); 7995 return; 7996 } 7997 } 7998 7999 if (handleEventFunc) { 8000 handleEventFunc(domEventName, targetNode, targetInst); 8001 } // When blurring, set the value attribute for number inputs 8002 8003 8004 if (domEventName === 'focusout') { 8005 handleControlledInputBlur(targetNode); 8006 } 8007 } 8008 8009 function registerEvents$2() { 8010 registerDirectEvent('onMouseEnter', ['mouseout', 'mouseover']); 8011 registerDirectEvent('onMouseLeave', ['mouseout', 'mouseover']); 8012 registerDirectEvent('onPointerEnter', ['pointerout', 'pointerover']); 8013 registerDirectEvent('onPointerLeave', ['pointerout', 'pointerover']); 8014 } 8015 /** 8016 * For almost every interaction we care about, there will be both a top-level 8017 * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that 8018 * we do not extract duplicate events. However, moving the mouse into the 8019 * browser from outside will not fire a `mouseout` event. In this case, we use 8020 * the `mouseover` top-level event. 8021 */ 8022 8023 8024 function extractEvents$2(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 8025 var isOverEvent = domEventName === 'mouseover' || domEventName === 'pointerover'; 8026 var isOutEvent = domEventName === 'mouseout' || domEventName === 'pointerout'; 8027 8028 if (isOverEvent && !isReplayingEvent(nativeEvent)) { 8029 // If this is an over event with a target, we might have already dispatched 8030 // the event in the out event of the other target. If this is replayed, 8031 // then it's because we couldn't dispatch against this target previously 8032 // so we have to do it now instead. 8033 var related = nativeEvent.relatedTarget || nativeEvent.fromElement; 8034 8035 if (related) { 8036 // If the related node is managed by React, we can assume that we have 8037 // already dispatched the corresponding events during its mouseout. 8038 if (getClosestInstanceFromNode(related) || isContainerMarkedAsRoot(related)) { 8039 return; 8040 } 8041 } 8042 } 8043 8044 if (!isOutEvent && !isOverEvent) { 8045 // Must not be a mouse or pointer in or out - ignoring. 8046 return; 8047 } 8048 8049 var win; // TODO: why is this nullable in the types but we read from it? 8050 8051 if (nativeEventTarget.window === nativeEventTarget) { 8052 // `nativeEventTarget` is probably a window object. 8053 win = nativeEventTarget; 8054 } else { 8055 // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8. 8056 var doc = nativeEventTarget.ownerDocument; 8057 8058 if (doc) { 8059 win = doc.defaultView || doc.parentWindow; 8060 } else { 8061 win = window; 8062 } 8063 } 8064 8065 var from; 8066 var to; 8067 8068 if (isOutEvent) { 8069 var _related = nativeEvent.relatedTarget || nativeEvent.toElement; 8070 8071 from = targetInst; 8072 to = _related ? getClosestInstanceFromNode(_related) : null; 8073 8074 if (to !== null) { 8075 var nearestMounted = getNearestMountedFiber(to); 8076 8077 if (to !== nearestMounted || to.tag !== HostComponent && to.tag !== HostText) { 8078 to = null; 8079 } 8080 } 8081 } else { 8082 // Moving to a node from outside the window. 8083 from = null; 8084 to = targetInst; 8085 } 8086 8087 if (from === to) { 8088 // Nothing pertains to our managed components. 8089 return; 8090 } 8091 8092 var SyntheticEventCtor = SyntheticMouseEvent; 8093 var leaveEventType = 'onMouseLeave'; 8094 var enterEventType = 'onMouseEnter'; 8095 var eventTypePrefix = 'mouse'; 8096 8097 if (domEventName === 'pointerout' || domEventName === 'pointerover') { 8098 SyntheticEventCtor = SyntheticPointerEvent; 8099 leaveEventType = 'onPointerLeave'; 8100 enterEventType = 'onPointerEnter'; 8101 eventTypePrefix = 'pointer'; 8102 } 8103 8104 var fromNode = from == null ? win : getNodeFromInstance(from); 8105 var toNode = to == null ? win : getNodeFromInstance(to); 8106 var leave = new SyntheticEventCtor(leaveEventType, eventTypePrefix + 'leave', from, nativeEvent, nativeEventTarget); 8107 leave.target = fromNode; 8108 leave.relatedTarget = toNode; 8109 var enter = null; // We should only process this nativeEvent if we are processing 8110 // the first ancestor. Next time, we will ignore the event. 8111 8112 var nativeTargetInst = getClosestInstanceFromNode(nativeEventTarget); 8113 8114 if (nativeTargetInst === targetInst) { 8115 var enterEvent = new SyntheticEventCtor(enterEventType, eventTypePrefix + 'enter', to, nativeEvent, nativeEventTarget); 8116 enterEvent.target = toNode; 8117 enterEvent.relatedTarget = fromNode; 8118 enter = enterEvent; 8119 } 8120 8121 accumulateEnterLeaveTwoPhaseListeners(dispatchQueue, leave, enter, from, to); 8122 } 8123 8124 /** 8125 * inlined Object.is polyfill to avoid requiring consumers ship their own 8126 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is 8127 */ 8128 function is(x, y) { 8129 return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y // eslint-disable-line no-self-compare 8130 ; 8131 } 8132 8133 var objectIs = typeof Object.is === 'function' ? Object.is : is; 8134 8135 /** 8136 * Performs equality by iterating through keys on an object and returning false 8137 * when any key has values which are not strictly equal between the arguments. 8138 * Returns true when the values of all keys are strictly equal. 8139 */ 8140 8141 function shallowEqual(objA, objB) { 8142 if (objectIs(objA, objB)) { 8143 return true; 8144 } 8145 8146 if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) { 8147 return false; 8148 } 8149 8150 var keysA = Object.keys(objA); 8151 var keysB = Object.keys(objB); 8152 8153 if (keysA.length !== keysB.length) { 8154 return false; 8155 } // Test for A's keys different from B. 8156 8157 8158 for (var i = 0; i < keysA.length; i++) { 8159 var currentKey = keysA[i]; 8160 8161 if (!hasOwnProperty.call(objB, currentKey) || !objectIs(objA[currentKey], objB[currentKey])) { 8162 return false; 8163 } 8164 } 8165 8166 return true; 8167 } 8168 8169 /** 8170 * Given any node return the first leaf node without children. 8171 * 8172 * @param {DOMElement|DOMTextNode} node 8173 * @return {DOMElement|DOMTextNode} 8174 */ 8175 8176 function getLeafNode(node) { 8177 while (node && node.firstChild) { 8178 node = node.firstChild; 8179 } 8180 8181 return node; 8182 } 8183 /** 8184 * Get the next sibling within a container. This will walk up the 8185 * DOM if a node's siblings have been exhausted. 8186 * 8187 * @param {DOMElement|DOMTextNode} node 8188 * @return {?DOMElement|DOMTextNode} 8189 */ 8190 8191 8192 function getSiblingNode(node) { 8193 while (node) { 8194 if (node.nextSibling) { 8195 return node.nextSibling; 8196 } 8197 8198 node = node.parentNode; 8199 } 8200 } 8201 /** 8202 * Get object describing the nodes which contain characters at offset. 8203 * 8204 * @param {DOMElement|DOMTextNode} root 8205 * @param {number} offset 8206 * @return {?object} 8207 */ 8208 8209 8210 function getNodeForCharacterOffset(root, offset) { 8211 var node = getLeafNode(root); 8212 var nodeStart = 0; 8213 var nodeEnd = 0; 8214 8215 while (node) { 8216 if (node.nodeType === TEXT_NODE) { 8217 nodeEnd = nodeStart + node.textContent.length; 8218 8219 if (nodeStart <= offset && nodeEnd >= offset) { 8220 return { 8221 node: node, 8222 offset: offset - nodeStart 8223 }; 8224 } 8225 8226 nodeStart = nodeEnd; 8227 } 8228 8229 node = getLeafNode(getSiblingNode(node)); 8230 } 8231 } 8232 8233 /** 8234 * @param {DOMElement} outerNode 8235 * @return {?object} 8236 */ 8237 8238 function getOffsets(outerNode) { 8239 var ownerDocument = outerNode.ownerDocument; 8240 var win = ownerDocument && ownerDocument.defaultView || window; 8241 var selection = win.getSelection && win.getSelection(); 8242 8243 if (!selection || selection.rangeCount === 0) { 8244 return null; 8245 } 8246 8247 var anchorNode = selection.anchorNode, 8248 anchorOffset = selection.anchorOffset, 8249 focusNode = selection.focusNode, 8250 focusOffset = selection.focusOffset; // In Firefox, anchorNode and focusNode can be "anonymous divs", e.g. the 8251 // up/down buttons on an <input type="number">. Anonymous divs do not seem to 8252 // expose properties, triggering a "Permission denied error" if any of its 8253 // properties are accessed. The only seemingly possible way to avoid erroring 8254 // is to access a property that typically works for non-anonymous divs and 8255 // catch any error that may otherwise arise. See 8256 // https://bugzilla.mozilla.org/show_bug.cgi?id=208427 8257 8258 try { 8259 /* eslint-disable no-unused-expressions */ 8260 anchorNode.nodeType; 8261 focusNode.nodeType; 8262 /* eslint-enable no-unused-expressions */ 8263 } catch (e) { 8264 return null; 8265 } 8266 8267 return getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset); 8268 } 8269 /** 8270 * Returns {start, end} where `start` is the character/codepoint index of 8271 * (anchorNode, anchorOffset) within the textContent of `outerNode`, and 8272 * `end` is the index of (focusNode, focusOffset). 8273 * 8274 * Returns null if you pass in garbage input but we should probably just crash. 8275 * 8276 * Exported only for testing. 8277 */ 8278 8279 function getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset) { 8280 var length = 0; 8281 var start = -1; 8282 var end = -1; 8283 var indexWithinAnchor = 0; 8284 var indexWithinFocus = 0; 8285 var node = outerNode; 8286 var parentNode = null; 8287 8288 outer: while (true) { 8289 var next = null; 8290 8291 while (true) { 8292 if (node === anchorNode && (anchorOffset === 0 || node.nodeType === TEXT_NODE)) { 8293 start = length + anchorOffset; 8294 } 8295 8296 if (node === focusNode && (focusOffset === 0 || node.nodeType === TEXT_NODE)) { 8297 end = length + focusOffset; 8298 } 8299 8300 if (node.nodeType === TEXT_NODE) { 8301 length += node.nodeValue.length; 8302 } 8303 8304 if ((next = node.firstChild) === null) { 8305 break; 8306 } // Moving from `node` to its first child `next`. 8307 8308 8309 parentNode = node; 8310 node = next; 8311 } 8312 8313 while (true) { 8314 if (node === outerNode) { 8315 // If `outerNode` has children, this is always the second time visiting 8316 // it. If it has no children, this is still the first loop, and the only 8317 // valid selection is anchorNode and focusNode both equal to this node 8318 // and both offsets 0, in which case we will have handled above. 8319 break outer; 8320 } 8321 8322 if (parentNode === anchorNode && ++indexWithinAnchor === anchorOffset) { 8323 start = length; 8324 } 8325 8326 if (parentNode === focusNode && ++indexWithinFocus === focusOffset) { 8327 end = length; 8328 } 8329 8330 if ((next = node.nextSibling) !== null) { 8331 break; 8332 } 8333 8334 node = parentNode; 8335 parentNode = node.parentNode; 8336 } // Moving from `node` to its next sibling `next`. 8337 8338 8339 node = next; 8340 } 8341 8342 if (start === -1 || end === -1) { 8343 // This should never happen. (Would happen if the anchor/focus nodes aren't 8344 // actually inside the passed-in node.) 8345 return null; 8346 } 8347 8348 return { 8349 start: start, 8350 end: end 8351 }; 8352 } 8353 /** 8354 * In modern non-IE browsers, we can support both forward and backward 8355 * selections. 8356 * 8357 * Note: IE10+ supports the Selection object, but it does not support 8358 * the `extend` method, which means that even in modern IE, it's not possible 8359 * to programmatically create a backward selection. Thus, for all IE 8360 * versions, we use the old IE API to create our selections. 8361 * 8362 * @param {DOMElement|DOMTextNode} node 8363 * @param {object} offsets 8364 */ 8365 8366 function setOffsets(node, offsets) { 8367 var doc = node.ownerDocument || document; 8368 var win = doc && doc.defaultView || window; // Edge fails with "Object expected" in some scenarios. 8369 // (For instance: TinyMCE editor used in a list component that supports pasting to add more, 8370 // fails when pasting 100+ items) 8371 8372 if (!win.getSelection) { 8373 return; 8374 } 8375 8376 var selection = win.getSelection(); 8377 var length = node.textContent.length; 8378 var start = Math.min(offsets.start, length); 8379 var end = offsets.end === undefined ? start : Math.min(offsets.end, length); // IE 11 uses modern selection, but doesn't support the extend method. 8380 // Flip backward selections, so we can set with a single range. 8381 8382 if (!selection.extend && start > end) { 8383 var temp = end; 8384 end = start; 8385 start = temp; 8386 } 8387 8388 var startMarker = getNodeForCharacterOffset(node, start); 8389 var endMarker = getNodeForCharacterOffset(node, end); 8390 8391 if (startMarker && endMarker) { 8392 if (selection.rangeCount === 1 && selection.anchorNode === startMarker.node && selection.anchorOffset === startMarker.offset && selection.focusNode === endMarker.node && selection.focusOffset === endMarker.offset) { 8393 return; 8394 } 8395 8396 var range = doc.createRange(); 8397 range.setStart(startMarker.node, startMarker.offset); 8398 selection.removeAllRanges(); 8399 8400 if (start > end) { 8401 selection.addRange(range); 8402 selection.extend(endMarker.node, endMarker.offset); 8403 } else { 8404 range.setEnd(endMarker.node, endMarker.offset); 8405 selection.addRange(range); 8406 } 8407 } 8408 } 8409 8410 function isTextNode(node) { 8411 return node && node.nodeType === TEXT_NODE; 8412 } 8413 8414 function containsNode(outerNode, innerNode) { 8415 if (!outerNode || !innerNode) { 8416 return false; 8417 } else if (outerNode === innerNode) { 8418 return true; 8419 } else if (isTextNode(outerNode)) { 8420 return false; 8421 } else if (isTextNode(innerNode)) { 8422 return containsNode(outerNode, innerNode.parentNode); 8423 } else if ('contains' in outerNode) { 8424 return outerNode.contains(innerNode); 8425 } else if (outerNode.compareDocumentPosition) { 8426 return !!(outerNode.compareDocumentPosition(innerNode) & 16); 8427 } else { 8428 return false; 8429 } 8430 } 8431 8432 function isInDocument(node) { 8433 return node && node.ownerDocument && containsNode(node.ownerDocument.documentElement, node); 8434 } 8435 8436 function isSameOriginFrame(iframe) { 8437 try { 8438 // Accessing the contentDocument of a HTMLIframeElement can cause the browser 8439 // to throw, e.g. if it has a cross-origin src attribute. 8440 // Safari will show an error in the console when the access results in "Blocked a frame with origin". e.g: 8441 // iframe.contentDocument.defaultView; 8442 // A safety way is to access one of the cross origin properties: Window or Location 8443 // Which might result in "SecurityError" DOM Exception and it is compatible to Safari. 8444 // https://html.spec.whatwg.org/multipage/browsers.html#integration-with-idl 8445 return typeof iframe.contentWindow.location.href === 'string'; 8446 } catch (err) { 8447 return false; 8448 } 8449 } 8450 8451 function getActiveElementDeep() { 8452 var win = window; 8453 var element = getActiveElement(); 8454 8455 while (element instanceof win.HTMLIFrameElement) { 8456 if (isSameOriginFrame(element)) { 8457 win = element.contentWindow; 8458 } else { 8459 return element; 8460 } 8461 8462 element = getActiveElement(win.document); 8463 } 8464 8465 return element; 8466 } 8467 /** 8468 * @ReactInputSelection: React input selection module. Based on Selection.js, 8469 * but modified to be suitable for react and has a couple of bug fixes (doesn't 8470 * assume buttons have range selections allowed). 8471 * Input selection module for React. 8472 */ 8473 8474 /** 8475 * @hasSelectionCapabilities: we get the element types that support selection 8476 * from https://html.spec.whatwg.org/#do-not-apply, looking at `selectionStart` 8477 * and `selectionEnd` rows. 8478 */ 8479 8480 8481 function hasSelectionCapabilities(elem) { 8482 var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase(); 8483 return nodeName && (nodeName === 'input' && (elem.type === 'text' || elem.type === 'search' || elem.type === 'tel' || elem.type === 'url' || elem.type === 'password') || nodeName === 'textarea' || elem.contentEditable === 'true'); 8484 } 8485 function getSelectionInformation() { 8486 var focusedElem = getActiveElementDeep(); 8487 return { 8488 focusedElem: focusedElem, 8489 selectionRange: hasSelectionCapabilities(focusedElem) ? getSelection(focusedElem) : null 8490 }; 8491 } 8492 /** 8493 * @restoreSelection: If any selection information was potentially lost, 8494 * restore it. This is useful when performing operations that could remove dom 8495 * nodes and place them back in, resulting in focus being lost. 8496 */ 8497 8498 function restoreSelection(priorSelectionInformation) { 8499 var curFocusedElem = getActiveElementDeep(); 8500 var priorFocusedElem = priorSelectionInformation.focusedElem; 8501 var priorSelectionRange = priorSelectionInformation.selectionRange; 8502 8503 if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) { 8504 if (priorSelectionRange !== null && hasSelectionCapabilities(priorFocusedElem)) { 8505 setSelection(priorFocusedElem, priorSelectionRange); 8506 } // Focusing a node can change the scroll position, which is undesirable 8507 8508 8509 var ancestors = []; 8510 var ancestor = priorFocusedElem; 8511 8512 while (ancestor = ancestor.parentNode) { 8513 if (ancestor.nodeType === ELEMENT_NODE) { 8514 ancestors.push({ 8515 element: ancestor, 8516 left: ancestor.scrollLeft, 8517 top: ancestor.scrollTop 8518 }); 8519 } 8520 } 8521 8522 if (typeof priorFocusedElem.focus === 'function') { 8523 priorFocusedElem.focus(); 8524 } 8525 8526 for (var i = 0; i < ancestors.length; i++) { 8527 var info = ancestors[i]; 8528 info.element.scrollLeft = info.left; 8529 info.element.scrollTop = info.top; 8530 } 8531 } 8532 } 8533 /** 8534 * @getSelection: Gets the selection bounds of a focused textarea, input or 8535 * contentEditable node. 8536 * -@input: Look up selection bounds of this input 8537 * -@return {start: selectionStart, end: selectionEnd} 8538 */ 8539 8540 function getSelection(input) { 8541 var selection; 8542 8543 if ('selectionStart' in input) { 8544 // Modern browser with input or textarea. 8545 selection = { 8546 start: input.selectionStart, 8547 end: input.selectionEnd 8548 }; 8549 } else { 8550 // Content editable or old IE textarea. 8551 selection = getOffsets(input); 8552 } 8553 8554 return selection || { 8555 start: 0, 8556 end: 0 8557 }; 8558 } 8559 /** 8560 * @setSelection: Sets the selection bounds of a textarea or input and focuses 8561 * the input. 8562 * -@input Set selection bounds of this input or textarea 8563 * -@offsets Object of same form that is returned from get* 8564 */ 8565 8566 function setSelection(input, offsets) { 8567 var start = offsets.start; 8568 var end = offsets.end; 8569 8570 if (end === undefined) { 8571 end = start; 8572 } 8573 8574 if ('selectionStart' in input) { 8575 input.selectionStart = start; 8576 input.selectionEnd = Math.min(end, input.value.length); 8577 } else { 8578 setOffsets(input, offsets); 8579 } 8580 } 8581 8582 var skipSelectionChangeEvent = canUseDOM && 'documentMode' in document && document.documentMode <= 11; 8583 8584 function registerEvents$3() { 8585 registerTwoPhaseEvent('onSelect', ['focusout', 'contextmenu', 'dragend', 'focusin', 'keydown', 'keyup', 'mousedown', 'mouseup', 'selectionchange']); 8586 } 8587 8588 var activeElement$1 = null; 8589 var activeElementInst$1 = null; 8590 var lastSelection = null; 8591 var mouseDown = false; 8592 /** 8593 * Get an object which is a unique representation of the current selection. 8594 * 8595 * The return value will not be consistent across nodes or browsers, but 8596 * two identical selections on the same node will return identical objects. 8597 */ 8598 8599 function getSelection$1(node) { 8600 if ('selectionStart' in node && hasSelectionCapabilities(node)) { 8601 return { 8602 start: node.selectionStart, 8603 end: node.selectionEnd 8604 }; 8605 } else { 8606 var win = node.ownerDocument && node.ownerDocument.defaultView || window; 8607 var selection = win.getSelection(); 8608 return { 8609 anchorNode: selection.anchorNode, 8610 anchorOffset: selection.anchorOffset, 8611 focusNode: selection.focusNode, 8612 focusOffset: selection.focusOffset 8613 }; 8614 } 8615 } 8616 /** 8617 * Get document associated with the event target. 8618 */ 8619 8620 8621 function getEventTargetDocument(eventTarget) { 8622 return eventTarget.window === eventTarget ? eventTarget.document : eventTarget.nodeType === DOCUMENT_NODE ? eventTarget : eventTarget.ownerDocument; 8623 } 8624 /** 8625 * Poll selection to see whether it's changed. 8626 * 8627 * @param {object} nativeEvent 8628 * @param {object} nativeEventTarget 8629 * @return {?SyntheticEvent} 8630 */ 8631 8632 8633 function constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget) { 8634 // Ensure we have the right element, and that the user is not dragging a 8635 // selection (this matches native `select` event behavior). In HTML5, select 8636 // fires only on input and textarea thus if there's no focused element we 8637 // won't dispatch. 8638 var doc = getEventTargetDocument(nativeEventTarget); 8639 8640 if (mouseDown || activeElement$1 == null || activeElement$1 !== getActiveElement(doc)) { 8641 return; 8642 } // Only fire when selection has actually changed. 8643 8644 8645 var currentSelection = getSelection$1(activeElement$1); 8646 8647 if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) { 8648 lastSelection = currentSelection; 8649 var listeners = accumulateTwoPhaseListeners(activeElementInst$1, 'onSelect'); 8650 8651 if (listeners.length > 0) { 8652 var event = new SyntheticEvent('onSelect', 'select', null, nativeEvent, nativeEventTarget); 8653 dispatchQueue.push({ 8654 event: event, 8655 listeners: listeners 8656 }); 8657 event.target = activeElement$1; 8658 } 8659 } 8660 } 8661 /** 8662 * This plugin creates an `onSelect` event that normalizes select events 8663 * across form elements. 8664 * 8665 * Supported elements are: 8666 * - input (see `isTextInputElement`) 8667 * - textarea 8668 * - contentEditable 8669 * 8670 * This differs from native browser implementations in the following ways: 8671 * - Fires on contentEditable fields as well as inputs. 8672 * - Fires for collapsed selection. 8673 * - Fires after user input. 8674 */ 8675 8676 8677 function extractEvents$3(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 8678 var targetNode = targetInst ? getNodeFromInstance(targetInst) : window; 8679 8680 switch (domEventName) { 8681 // Track the input node that has focus. 8682 case 'focusin': 8683 if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') { 8684 activeElement$1 = targetNode; 8685 activeElementInst$1 = targetInst; 8686 lastSelection = null; 8687 } 8688 8689 break; 8690 8691 case 'focusout': 8692 activeElement$1 = null; 8693 activeElementInst$1 = null; 8694 lastSelection = null; 8695 break; 8696 // Don't fire the event while the user is dragging. This matches the 8697 // semantics of the native select event. 8698 8699 case 'mousedown': 8700 mouseDown = true; 8701 break; 8702 8703 case 'contextmenu': 8704 case 'mouseup': 8705 case 'dragend': 8706 mouseDown = false; 8707 constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget); 8708 break; 8709 // Chrome and IE fire non-standard event when selection is changed (and 8710 // sometimes when it hasn't). IE's event fires out of order with respect 8711 // to key and input events on deletion, so we discard it. 8712 // 8713 // Firefox doesn't support selectionchange, so check selection status 8714 // after each key entry. The selection changes after keydown and before 8715 // keyup, but we check on keydown as well in the case of holding down a 8716 // key, when multiple keydown events are fired but only one keyup is. 8717 // This is also our approach for IE handling, for the reason above. 8718 8719 case 'selectionchange': 8720 if (skipSelectionChangeEvent) { 8721 break; 8722 } 8723 8724 // falls through 8725 8726 case 'keydown': 8727 case 'keyup': 8728 constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget); 8729 } 8730 } 8731 8732 /** 8733 * Generate a mapping of standard vendor prefixes using the defined style property and event name. 8734 * 8735 * @param {string} styleProp 8736 * @param {string} eventName 8737 * @returns {object} 8738 */ 8739 8740 function makePrefixMap(styleProp, eventName) { 8741 var prefixes = {}; 8742 prefixes[styleProp.toLowerCase()] = eventName.toLowerCase(); 8743 prefixes['Webkit' + styleProp] = 'webkit' + eventName; 8744 prefixes['Moz' + styleProp] = 'moz' + eventName; 8745 return prefixes; 8746 } 8747 /** 8748 * A list of event names to a configurable list of vendor prefixes. 8749 */ 8750 8751 8752 var vendorPrefixes = { 8753 animationend: makePrefixMap('Animation', 'AnimationEnd'), 8754 animationiteration: makePrefixMap('Animation', 'AnimationIteration'), 8755 animationstart: makePrefixMap('Animation', 'AnimationStart'), 8756 transitionend: makePrefixMap('Transition', 'TransitionEnd') 8757 }; 8758 /** 8759 * Event names that have already been detected and prefixed (if applicable). 8760 */ 8761 8762 var prefixedEventNames = {}; 8763 /** 8764 * Element to check for prefixes on. 8765 */ 8766 8767 var style = {}; 8768 /** 8769 * Bootstrap if a DOM exists. 8770 */ 8771 8772 if (canUseDOM) { 8773 style = document.createElement('div').style; // On some platforms, in particular some releases of Android 4.x, 8774 // the un-prefixed "animation" and "transition" properties are defined on the 8775 // style object but the events that fire will still be prefixed, so we need 8776 // to check if the un-prefixed events are usable, and if not remove them from the map. 8777 8778 if (!('AnimationEvent' in window)) { 8779 delete vendorPrefixes.animationend.animation; 8780 delete vendorPrefixes.animationiteration.animation; 8781 delete vendorPrefixes.animationstart.animation; 8782 } // Same as above 8783 8784 8785 if (!('TransitionEvent' in window)) { 8786 delete vendorPrefixes.transitionend.transition; 8787 } 8788 } 8789 /** 8790 * Attempts to determine the correct vendor prefixed event name. 8791 * 8792 * @param {string} eventName 8793 * @returns {string} 8794 */ 8795 8796 8797 function getVendorPrefixedEventName(eventName) { 8798 if (prefixedEventNames[eventName]) { 8799 return prefixedEventNames[eventName]; 8800 } else if (!vendorPrefixes[eventName]) { 8801 return eventName; 8802 } 8803 8804 var prefixMap = vendorPrefixes[eventName]; 8805 8806 for (var styleProp in prefixMap) { 8807 if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) { 8808 return prefixedEventNames[eventName] = prefixMap[styleProp]; 8809 } 8810 } 8811 8812 return eventName; 8813 } 8814 8815 var ANIMATION_END = getVendorPrefixedEventName('animationend'); 8816 var ANIMATION_ITERATION = getVendorPrefixedEventName('animationiteration'); 8817 var ANIMATION_START = getVendorPrefixedEventName('animationstart'); 8818 var TRANSITION_END = getVendorPrefixedEventName('transitionend'); 8819 8820 var topLevelEventsToReactNames = new Map(); // NOTE: Capitalization is important in this list! 8821 // 8822 // E.g. it needs "pointerDown", not "pointerdown". 8823 // This is because we derive both React name ("onPointerDown") 8824 // and DOM name ("pointerdown") from the same list. 8825 // 8826 // Exceptions that don't match this convention are listed separately. 8827 // 8828 // prettier-ignore 8829 8830 var simpleEventPluginEvents = ['abort', 'auxClick', 'cancel', 'canPlay', 'canPlayThrough', 'click', 'close', 'contextMenu', 'copy', 'cut', 'drag', 'dragEnd', 'dragEnter', 'dragExit', 'dragLeave', 'dragOver', 'dragStart', 'drop', 'durationChange', 'emptied', 'encrypted', 'ended', 'error', 'gotPointerCapture', 'input', 'invalid', 'keyDown', 'keyPress', 'keyUp', 'load', 'loadedData', 'loadedMetadata', 'loadStart', 'lostPointerCapture', 'mouseDown', 'mouseMove', 'mouseOut', 'mouseOver', 'mouseUp', 'paste', 'pause', 'play', 'playing', 'pointerCancel', 'pointerDown', 'pointerMove', 'pointerOut', 'pointerOver', 'pointerUp', 'progress', 'rateChange', 'reset', 'resize', 'seeked', 'seeking', 'stalled', 'submit', 'suspend', 'timeUpdate', 'touchCancel', 'touchEnd', 'touchStart', 'volumeChange', 'scroll', 'toggle', 'touchMove', 'waiting', 'wheel']; 8831 8832 function registerSimpleEvent(domEventName, reactName) { 8833 topLevelEventsToReactNames.set(domEventName, reactName); 8834 registerTwoPhaseEvent(reactName, [domEventName]); 8835 } 8836 8837 function registerSimpleEvents() { 8838 for (var i = 0; i < simpleEventPluginEvents.length; i++) { 8839 var eventName = simpleEventPluginEvents[i]; 8840 var domEventName = eventName.toLowerCase(); 8841 var capitalizedEvent = eventName[0].toUpperCase() + eventName.slice(1); 8842 registerSimpleEvent(domEventName, 'on' + capitalizedEvent); 8843 } // Special cases where event names don't match. 8844 8845 8846 registerSimpleEvent(ANIMATION_END, 'onAnimationEnd'); 8847 registerSimpleEvent(ANIMATION_ITERATION, 'onAnimationIteration'); 8848 registerSimpleEvent(ANIMATION_START, 'onAnimationStart'); 8849 registerSimpleEvent('dblclick', 'onDoubleClick'); 8850 registerSimpleEvent('focusin', 'onFocus'); 8851 registerSimpleEvent('focusout', 'onBlur'); 8852 registerSimpleEvent(TRANSITION_END, 'onTransitionEnd'); 8853 } 8854 8855 function extractEvents$4(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 8856 var reactName = topLevelEventsToReactNames.get(domEventName); 8857 8858 if (reactName === undefined) { 8859 return; 8860 } 8861 8862 var SyntheticEventCtor = SyntheticEvent; 8863 var reactEventType = domEventName; 8864 8865 switch (domEventName) { 8866 case 'keypress': 8867 // Firefox creates a keypress event for function keys too. This removes 8868 // the unwanted keypress events. Enter is however both printable and 8869 // non-printable. One would expect Tab to be as well (but it isn't). 8870 if (getEventCharCode(nativeEvent) === 0) { 8871 return; 8872 } 8873 8874 /* falls through */ 8875 8876 case 'keydown': 8877 case 'keyup': 8878 SyntheticEventCtor = SyntheticKeyboardEvent; 8879 break; 8880 8881 case 'focusin': 8882 reactEventType = 'focus'; 8883 SyntheticEventCtor = SyntheticFocusEvent; 8884 break; 8885 8886 case 'focusout': 8887 reactEventType = 'blur'; 8888 SyntheticEventCtor = SyntheticFocusEvent; 8889 break; 8890 8891 case 'beforeblur': 8892 case 'afterblur': 8893 SyntheticEventCtor = SyntheticFocusEvent; 8894 break; 8895 8896 case 'click': 8897 // Firefox creates a click event on right mouse clicks. This removes the 8898 // unwanted click events. 8899 if (nativeEvent.button === 2) { 8900 return; 8901 } 8902 8903 /* falls through */ 8904 8905 case 'auxclick': 8906 case 'dblclick': 8907 case 'mousedown': 8908 case 'mousemove': 8909 case 'mouseup': // TODO: Disabled elements should not respond to mouse events 8910 8911 /* falls through */ 8912 8913 case 'mouseout': 8914 case 'mouseover': 8915 case 'contextmenu': 8916 SyntheticEventCtor = SyntheticMouseEvent; 8917 break; 8918 8919 case 'drag': 8920 case 'dragend': 8921 case 'dragenter': 8922 case 'dragexit': 8923 case 'dragleave': 8924 case 'dragover': 8925 case 'dragstart': 8926 case 'drop': 8927 SyntheticEventCtor = SyntheticDragEvent; 8928 break; 8929 8930 case 'touchcancel': 8931 case 'touchend': 8932 case 'touchmove': 8933 case 'touchstart': 8934 SyntheticEventCtor = SyntheticTouchEvent; 8935 break; 8936 8937 case ANIMATION_END: 8938 case ANIMATION_ITERATION: 8939 case ANIMATION_START: 8940 SyntheticEventCtor = SyntheticAnimationEvent; 8941 break; 8942 8943 case TRANSITION_END: 8944 SyntheticEventCtor = SyntheticTransitionEvent; 8945 break; 8946 8947 case 'scroll': 8948 SyntheticEventCtor = SyntheticUIEvent; 8949 break; 8950 8951 case 'wheel': 8952 SyntheticEventCtor = SyntheticWheelEvent; 8953 break; 8954 8955 case 'copy': 8956 case 'cut': 8957 case 'paste': 8958 SyntheticEventCtor = SyntheticClipboardEvent; 8959 break; 8960 8961 case 'gotpointercapture': 8962 case 'lostpointercapture': 8963 case 'pointercancel': 8964 case 'pointerdown': 8965 case 'pointermove': 8966 case 'pointerout': 8967 case 'pointerover': 8968 case 'pointerup': 8969 SyntheticEventCtor = SyntheticPointerEvent; 8970 break; 8971 } 8972 8973 var inCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0; 8974 8975 { 8976 // Some events don't bubble in the browser. 8977 // In the past, React has always bubbled them, but this can be surprising. 8978 // We're going to try aligning closer to the browser behavior by not bubbling 8979 // them in React either. We'll start by not bubbling onScroll, and then expand. 8980 var accumulateTargetOnly = !inCapturePhase && // TODO: ideally, we'd eventually add all events from 8981 // nonDelegatedEvents list in DOMPluginEventSystem. 8982 // Then we can remove this special list. 8983 // This is a breaking change that can wait until React 18. 8984 domEventName === 'scroll'; 8985 8986 var _listeners = accumulateSinglePhaseListeners(targetInst, reactName, nativeEvent.type, inCapturePhase, accumulateTargetOnly); 8987 8988 if (_listeners.length > 0) { 8989 // Intentionally create event lazily. 8990 var _event = new SyntheticEventCtor(reactName, reactEventType, null, nativeEvent, nativeEventTarget); 8991 8992 dispatchQueue.push({ 8993 event: _event, 8994 listeners: _listeners 8995 }); 8996 } 8997 } 8998 } 8999 9000 // TODO: remove top-level side effect. 9001 registerSimpleEvents(); 9002 registerEvents$2(); 9003 registerEvents$1(); 9004 registerEvents$3(); 9005 registerEvents(); 9006 9007 function extractEvents$5(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 9008 // TODO: we should remove the concept of a "SimpleEventPlugin". 9009 // This is the basic functionality of the event system. All 9010 // the other plugins are essentially polyfills. So the plugin 9011 // should probably be inlined somewhere and have its logic 9012 // 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 var didWarnAboutMaps; 12998 var didWarnAboutGenerators; 12999 var didWarnAboutStringRefs; 13000 var ownerHasKeyUseWarning; 13001 var ownerHasFunctionTypeWarning; 13002 13003 var warnForMissingKey = function (child, returnFiber) {}; 13004 13005 { 13006 didWarnAboutMaps = false; 13007 didWarnAboutGenerators = false; 13008 didWarnAboutStringRefs = {}; 13009 /** 13010 * Warn if there's no key explicitly set on dynamic arrays of children or 13011 * object keys are not valid. This allows us to keep track of children between 13012 * updates. 13013 */ 13014 13015 ownerHasKeyUseWarning = {}; 13016 ownerHasFunctionTypeWarning = {}; 13017 13018 warnForMissingKey = function (child, returnFiber) { 13019 if (child === null || typeof child !== 'object') { 13020 return; 13021 } 13022 13023 if (!child._store || child._store.validated || child.key != null) { 13024 return; 13025 } 13026 13027 if (typeof child._store !== 'object') { 13028 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.'); 13029 } 13030 13031 child._store.validated = true; 13032 var componentName = getComponentNameFromFiber(returnFiber) || 'Component'; 13033 13034 if (ownerHasKeyUseWarning[componentName]) { 13035 return; 13036 } 13037 13038 ownerHasKeyUseWarning[componentName] = true; 13039 13040 error('Each child in a list should have a unique ' + '"key" prop. See https://reactjs.org/link/warning-keys for ' + 'more information.'); 13041 }; 13042 } 13043 13044 function isReactClass(type) { 13045 return type.prototype && type.prototype.isReactComponent; 13046 } 13047 13048 function coerceRef(returnFiber, current, element) { 13049 var mixedRef = element.ref; 13050 13051 if (mixedRef !== null && typeof mixedRef !== 'function' && typeof mixedRef !== 'object') { 13052 { 13053 // TODO: Clean this up once we turn on the string ref warning for 13054 // everyone, because the strict mode case will no longer be relevant 13055 if ((returnFiber.mode & StrictLegacyMode || warnAboutStringRefs) && // We warn in ReactElement.js if owner and self are equal for string refs 13056 // because these cannot be automatically converted to an arrow function 13057 // using a codemod. Therefore, we don't have to warn about string refs again. 13058 !(element._owner && element._self && element._owner.stateNode !== element._self) && // Will already throw with "Function components cannot have string refs" 13059 !(element._owner && element._owner.tag !== ClassComponent) && // Will already warn with "Function components cannot be given refs" 13060 !(typeof element.type === 'function' && !isReactClass(element.type)) && // Will already throw with "Element ref was specified as a string (someStringRef) but no owner was set" 13061 element._owner) { 13062 var componentName = getComponentNameFromFiber(returnFiber) || 'Component'; 13063 13064 if (!didWarnAboutStringRefs[componentName]) { 13065 { 13066 error('Component "%s" contains the string ref "%s". Support for string refs ' + 'will be removed in a future major release. We recommend using ' + 'useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref', componentName, mixedRef); 13067 } 13068 13069 didWarnAboutStringRefs[componentName] = true; 13070 } 13071 } 13072 } 13073 13074 if (element._owner) { 13075 var owner = element._owner; 13076 var inst; 13077 13078 if (owner) { 13079 var ownerFiber = owner; 13080 13081 if (ownerFiber.tag !== ClassComponent) { 13082 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'); 13083 } 13084 13085 inst = ownerFiber.stateNode; 13086 } 13087 13088 if (!inst) { 13089 throw new Error("Missing owner for string ref " + mixedRef + ". This error is likely caused by a " + 'bug in React. Please file an issue.'); 13090 } // Assigning this to a const so Flow knows it won't change in the closure 13091 13092 13093 var resolvedInst = inst; 13094 13095 { 13096 checkPropStringCoercion(mixedRef, 'ref'); 13097 } 13098 13099 var stringRef = '' + mixedRef; // Check if previous string ref matches new string ref 13100 13101 if (current !== null && current.ref !== null && typeof current.ref === 'function' && current.ref._stringRef === stringRef) { 13102 return current.ref; 13103 } 13104 13105 var ref = function (value) { 13106 var refs = resolvedInst.refs; 13107 13108 if (value === null) { 13109 delete refs[stringRef]; 13110 } else { 13111 refs[stringRef] = value; 13112 } 13113 }; 13114 13115 ref._stringRef = stringRef; 13116 return ref; 13117 } else { 13118 if (typeof mixedRef !== 'string') { 13119 throw new Error('Expected ref to be a function, a string, an object returned by React.createRef(), or null.'); 13120 } 13121 13122 if (!element._owner) { 13123 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.'); 13124 } 13125 } 13126 } 13127 13128 return mixedRef; 13129 } 13130 13131 function throwOnInvalidObjectType(returnFiber, newChild) { 13132 var childString = Object.prototype.toString.call(newChild); 13133 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.'); 13134 } 13135 13136 function warnOnFunctionType(returnFiber) { 13137 { 13138 var componentName = getComponentNameFromFiber(returnFiber) || 'Component'; 13139 13140 if (ownerHasFunctionTypeWarning[componentName]) { 13141 return; 13142 } 13143 13144 ownerHasFunctionTypeWarning[componentName] = true; 13145 13146 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.'); 13147 } 13148 } 13149 13150 function resolveLazy(lazyType) { 13151 var payload = lazyType._payload; 13152 var init = lazyType._init; 13153 return init(payload); 13154 } // This wrapper function exists because I expect to clone the code in each path 13155 // to be able to optimize each path individually by branching early. This needs 13156 // a compiler or we can do it manually. Helpers that don't need this branching 13157 // live outside of this function. 13158 13159 13160 function ChildReconciler(shouldTrackSideEffects) { 13161 function deleteChild(returnFiber, childToDelete) { 13162 if (!shouldTrackSideEffects) { 13163 // Noop. 13164 return; 13165 } 13166 13167 var deletions = returnFiber.deletions; 13168 13169 if (deletions === null) { 13170 returnFiber.deletions = [childToDelete]; 13171 returnFiber.flags |= ChildDeletion; 13172 } else { 13173 deletions.push(childToDelete); 13174 } 13175 } 13176 13177 function deleteRemainingChildren(returnFiber, currentFirstChild) { 13178 if (!shouldTrackSideEffects) { 13179 // Noop. 13180 return null; 13181 } // TODO: For the shouldClone case, this could be micro-optimized a bit by 13182 // assuming that after the first child we've already added everything. 13183 13184 13185 var childToDelete = currentFirstChild; 13186 13187 while (childToDelete !== null) { 13188 deleteChild(returnFiber, childToDelete); 13189 childToDelete = childToDelete.sibling; 13190 } 13191 13192 return null; 13193 } 13194 13195 function mapRemainingChildren(returnFiber, currentFirstChild) { 13196 // Add the remaining children to a temporary map so that we can find them by 13197 // keys quickly. Implicit (null) keys get added to this set with their index 13198 // instead. 13199 var existingChildren = new Map(); 13200 var existingChild = currentFirstChild; 13201 13202 while (existingChild !== null) { 13203 if (existingChild.key !== null) { 13204 existingChildren.set(existingChild.key, existingChild); 13205 } else { 13206 existingChildren.set(existingChild.index, existingChild); 13207 } 13208 13209 existingChild = existingChild.sibling; 13210 } 13211 13212 return existingChildren; 13213 } 13214 13215 function useFiber(fiber, pendingProps) { 13216 // We currently set sibling to null and index to 0 here because it is easy 13217 // to forget to do before returning it. E.g. for the single child case. 13218 var clone = createWorkInProgress(fiber, pendingProps); 13219 clone.index = 0; 13220 clone.sibling = null; 13221 return clone; 13222 } 13223 13224 function placeChild(newFiber, lastPlacedIndex, newIndex) { 13225 newFiber.index = newIndex; 13226 13227 if (!shouldTrackSideEffects) { 13228 // During hydration, the useId algorithm needs to know which fibers are 13229 // part of a list of children (arrays, iterators). 13230 newFiber.flags |= Forked; 13231 return lastPlacedIndex; 13232 } 13233 13234 var current = newFiber.alternate; 13235 13236 if (current !== null) { 13237 var oldIndex = current.index; 13238 13239 if (oldIndex < lastPlacedIndex) { 13240 // This is a move. 13241 newFiber.flags |= Placement; 13242 return lastPlacedIndex; 13243 } else { 13244 // This item can stay in place. 13245 return oldIndex; 13246 } 13247 } else { 13248 // This is an insertion. 13249 newFiber.flags |= Placement; 13250 return lastPlacedIndex; 13251 } 13252 } 13253 13254 function placeSingleChild(newFiber) { 13255 // This is simpler for the single child case. We only need to do a 13256 // placement for inserting new children. 13257 if (shouldTrackSideEffects && newFiber.alternate === null) { 13258 newFiber.flags |= Placement; 13259 } 13260 13261 return newFiber; 13262 } 13263 13264 function updateTextNode(returnFiber, current, textContent, lanes) { 13265 if (current === null || current.tag !== HostText) { 13266 // Insert 13267 var created = createFiberFromText(textContent, returnFiber.mode, lanes); 13268 created.return = returnFiber; 13269 return created; 13270 } else { 13271 // Update 13272 var existing = useFiber(current, textContent); 13273 existing.return = returnFiber; 13274 return existing; 13275 } 13276 } 13277 13278 function updateElement(returnFiber, current, element, lanes) { 13279 var elementType = element.type; 13280 13281 if (elementType === REACT_FRAGMENT_TYPE) { 13282 return updateFragment(returnFiber, current, element.props.children, lanes, element.key); 13283 } 13284 13285 if (current !== null) { 13286 if (current.elementType === elementType || ( // Keep this check inline so it only runs on the false path: 13287 isCompatibleFamilyForHotReloading(current, element) ) || // Lazy types should reconcile their resolved type. 13288 // We need to do this after the Hot Reloading check above, 13289 // because hot reloading has different semantics than prod because 13290 // it doesn't resuspend. So we can't let the call below suspend. 13291 typeof elementType === 'object' && elementType !== null && elementType.$$typeof === REACT_LAZY_TYPE && resolveLazy(elementType) === current.type) { 13292 // Move based on index 13293 var existing = useFiber(current, element.props); 13294 existing.ref = coerceRef(returnFiber, current, element); 13295 existing.return = returnFiber; 13296 13297 { 13298 existing._debugSource = element._source; 13299 existing._debugOwner = element._owner; 13300 } 13301 13302 return existing; 13303 } 13304 } // Insert 13305 13306 13307 var created = createFiberFromElement(element, returnFiber.mode, lanes); 13308 created.ref = coerceRef(returnFiber, current, element); 13309 created.return = returnFiber; 13310 return created; 13311 } 13312 13313 function updatePortal(returnFiber, current, portal, lanes) { 13314 if (current === null || current.tag !== HostPortal || current.stateNode.containerInfo !== portal.containerInfo || current.stateNode.implementation !== portal.implementation) { 13315 // Insert 13316 var created = createFiberFromPortal(portal, returnFiber.mode, lanes); 13317 created.return = returnFiber; 13318 return created; 13319 } else { 13320 // Update 13321 var existing = useFiber(current, portal.children || []); 13322 existing.return = returnFiber; 13323 return existing; 13324 } 13325 } 13326 13327 function updateFragment(returnFiber, current, fragment, lanes, key) { 13328 if (current === null || current.tag !== Fragment) { 13329 // Insert 13330 var created = createFiberFromFragment(fragment, returnFiber.mode, lanes, key); 13331 created.return = returnFiber; 13332 return created; 13333 } else { 13334 // Update 13335 var existing = useFiber(current, fragment); 13336 existing.return = returnFiber; 13337 return existing; 13338 } 13339 } 13340 13341 function createChild(returnFiber, newChild, lanes) { 13342 if (typeof newChild === 'string' && newChild !== '' || typeof newChild === 'number') { 13343 // Text nodes don't have keys. If the previous node is implicitly keyed 13344 // we can continue to replace it without aborting even if it is not a text 13345 // node. 13346 var created = createFiberFromText('' + newChild, returnFiber.mode, lanes); 13347 created.return = returnFiber; 13348 return created; 13349 } 13350 13351 if (typeof newChild === 'object' && newChild !== null) { 13352 switch (newChild.$$typeof) { 13353 case REACT_ELEMENT_TYPE: 13354 { 13355 var _created = createFiberFromElement(newChild, returnFiber.mode, lanes); 13356 13357 _created.ref = coerceRef(returnFiber, null, newChild); 13358 _created.return = returnFiber; 13359 return _created; 13360 } 13361 13362 case REACT_PORTAL_TYPE: 13363 { 13364 var _created2 = createFiberFromPortal(newChild, returnFiber.mode, lanes); 13365 13366 _created2.return = returnFiber; 13367 return _created2; 13368 } 13369 13370 case REACT_LAZY_TYPE: 13371 { 13372 var payload = newChild._payload; 13373 var init = newChild._init; 13374 return createChild(returnFiber, init(payload), lanes); 13375 } 13376 } 13377 13378 if (isArray(newChild) || getIteratorFn(newChild)) { 13379 var _created3 = createFiberFromFragment(newChild, returnFiber.mode, lanes, null); 13380 13381 _created3.return = returnFiber; 13382 return _created3; 13383 } 13384 13385 throwOnInvalidObjectType(returnFiber, newChild); 13386 } 13387 13388 { 13389 if (typeof newChild === 'function') { 13390 warnOnFunctionType(returnFiber); 13391 } 13392 } 13393 13394 return null; 13395 } 13396 13397 function updateSlot(returnFiber, oldFiber, newChild, lanes) { 13398 // Update the fiber if the keys match, otherwise return null. 13399 var key = oldFiber !== null ? oldFiber.key : null; 13400 13401 if (typeof newChild === 'string' && newChild !== '' || typeof newChild === 'number') { 13402 // Text nodes don't have keys. If the previous node is implicitly keyed 13403 // we can continue to replace it without aborting even if it is not a text 13404 // node. 13405 if (key !== null) { 13406 return null; 13407 } 13408 13409 return updateTextNode(returnFiber, oldFiber, '' + newChild, lanes); 13410 } 13411 13412 if (typeof newChild === 'object' && newChild !== null) { 13413 switch (newChild.$$typeof) { 13414 case REACT_ELEMENT_TYPE: 13415 { 13416 if (newChild.key === key) { 13417 return updateElement(returnFiber, oldFiber, newChild, lanes); 13418 } else { 13419 return null; 13420 } 13421 } 13422 13423 case REACT_PORTAL_TYPE: 13424 { 13425 if (newChild.key === key) { 13426 return updatePortal(returnFiber, oldFiber, newChild, lanes); 13427 } else { 13428 return null; 13429 } 13430 } 13431 13432 case REACT_LAZY_TYPE: 13433 { 13434 var payload = newChild._payload; 13435 var init = newChild._init; 13436 return updateSlot(returnFiber, oldFiber, init(payload), lanes); 13437 } 13438 } 13439 13440 if (isArray(newChild) || getIteratorFn(newChild)) { 13441 if (key !== null) { 13442 return null; 13443 } 13444 13445 return updateFragment(returnFiber, oldFiber, newChild, lanes, null); 13446 } 13447 13448 throwOnInvalidObjectType(returnFiber, newChild); 13449 } 13450 13451 { 13452 if (typeof newChild === 'function') { 13453 warnOnFunctionType(returnFiber); 13454 } 13455 } 13456 13457 return null; 13458 } 13459 13460 function updateFromMap(existingChildren, returnFiber, newIdx, newChild, lanes) { 13461 if (typeof newChild === 'string' && newChild !== '' || typeof newChild === 'number') { 13462 // Text nodes don't have keys, so we neither have to check the old nor 13463 // new node for the key. If both are text nodes, they match. 13464 var matchedFiber = existingChildren.get(newIdx) || null; 13465 return updateTextNode(returnFiber, matchedFiber, '' + newChild, lanes); 13466 } 13467 13468 if (typeof newChild === 'object' && newChild !== null) { 13469 switch (newChild.$$typeof) { 13470 case REACT_ELEMENT_TYPE: 13471 { 13472 var _matchedFiber = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null; 13473 13474 return updateElement(returnFiber, _matchedFiber, newChild, lanes); 13475 } 13476 13477 case REACT_PORTAL_TYPE: 13478 { 13479 var _matchedFiber2 = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null; 13480 13481 return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); 13482 } 13483 13484 case REACT_LAZY_TYPE: 13485 var payload = newChild._payload; 13486 var init = newChild._init; 13487 return updateFromMap(existingChildren, returnFiber, newIdx, init(payload), lanes); 13488 } 13489 13490 if (isArray(newChild) || getIteratorFn(newChild)) { 13491 var _matchedFiber3 = existingChildren.get(newIdx) || null; 13492 13493 return updateFragment(returnFiber, _matchedFiber3, newChild, lanes, null); 13494 } 13495 13496 throwOnInvalidObjectType(returnFiber, newChild); 13497 } 13498 13499 { 13500 if (typeof newChild === 'function') { 13501 warnOnFunctionType(returnFiber); 13502 } 13503 } 13504 13505 return null; 13506 } 13507 /** 13508 * Warns if there is a duplicate or missing key 13509 */ 13510 13511 13512 function warnOnInvalidKey(child, knownKeys, returnFiber) { 13513 { 13514 if (typeof child !== 'object' || child === null) { 13515 return knownKeys; 13516 } 13517 13518 switch (child.$$typeof) { 13519 case REACT_ELEMENT_TYPE: 13520 case REACT_PORTAL_TYPE: 13521 warnForMissingKey(child, returnFiber); 13522 var key = child.key; 13523 13524 if (typeof key !== 'string') { 13525 break; 13526 } 13527 13528 if (knownKeys === null) { 13529 knownKeys = new Set(); 13530 knownKeys.add(key); 13531 break; 13532 } 13533 13534 if (!knownKeys.has(key)) { 13535 knownKeys.add(key); 13536 break; 13537 } 13538 13539 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); 13540 13541 break; 13542 13543 case REACT_LAZY_TYPE: 13544 var payload = child._payload; 13545 var init = child._init; 13546 warnOnInvalidKey(init(payload), knownKeys, returnFiber); 13547 break; 13548 } 13549 } 13550 13551 return knownKeys; 13552 } 13553 13554 function reconcileChildrenArray(returnFiber, currentFirstChild, newChildren, lanes) { 13555 // This algorithm can't optimize by searching from both ends since we 13556 // don't have backpointers on fibers. I'm trying to see how far we can get 13557 // with that model. If it ends up not being worth the tradeoffs, we can 13558 // add it later. 13559 // Even with a two ended optimization, we'd want to optimize for the case 13560 // where there are few changes and brute force the comparison instead of 13561 // going for the Map. It'd like to explore hitting that path first in 13562 // forward-only mode and only go for the Map once we notice that we need 13563 // lots of look ahead. This doesn't handle reversal as well as two ended 13564 // search but that's unusual. Besides, for the two ended optimization to 13565 // work on Iterables, we'd need to copy the whole set. 13566 // In this first iteration, we'll just live with hitting the bad case 13567 // (adding everything to a Map) in for every insert/move. 13568 // If you change this code, also update reconcileChildrenIterator() which 13569 // uses the same algorithm. 13570 { 13571 // First, validate keys. 13572 var knownKeys = null; 13573 13574 for (var i = 0; i < newChildren.length; i++) { 13575 var child = newChildren[i]; 13576 knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); 13577 } 13578 } 13579 13580 var resultingFirstChild = null; 13581 var previousNewFiber = null; 13582 var oldFiber = currentFirstChild; 13583 var lastPlacedIndex = 0; 13584 var newIdx = 0; 13585 var nextOldFiber = null; 13586 13587 for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { 13588 if (oldFiber.index > newIdx) { 13589 nextOldFiber = oldFiber; 13590 oldFiber = null; 13591 } else { 13592 nextOldFiber = oldFiber.sibling; 13593 } 13594 13595 var newFiber = updateSlot(returnFiber, oldFiber, newChildren[newIdx], lanes); 13596 13597 if (newFiber === null) { 13598 // TODO: This breaks on empty slots like null children. That's 13599 // unfortunate because it triggers the slow path all the time. We need 13600 // a better way to communicate whether this was a miss or null, 13601 // boolean, undefined, etc. 13602 if (oldFiber === null) { 13603 oldFiber = nextOldFiber; 13604 } 13605 13606 break; 13607 } 13608 13609 if (shouldTrackSideEffects) { 13610 if (oldFiber && newFiber.alternate === null) { 13611 // We matched the slot, but we didn't reuse the existing fiber, so we 13612 // need to delete the existing child. 13613 deleteChild(returnFiber, oldFiber); 13614 } 13615 } 13616 13617 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); 13618 13619 if (previousNewFiber === null) { 13620 // TODO: Move out of the loop. This only happens for the first run. 13621 resultingFirstChild = newFiber; 13622 } else { 13623 // TODO: Defer siblings if we're not at the right index for this slot. 13624 // I.e. if we had null values before, then we want to defer this 13625 // for each null value. However, we also don't want to call updateSlot 13626 // with the previous one. 13627 previousNewFiber.sibling = newFiber; 13628 } 13629 13630 previousNewFiber = newFiber; 13631 oldFiber = nextOldFiber; 13632 } 13633 13634 if (newIdx === newChildren.length) { 13635 // We've reached the end of the new children. We can delete the rest. 13636 deleteRemainingChildren(returnFiber, oldFiber); 13637 13638 if (getIsHydrating()) { 13639 var numberOfForks = newIdx; 13640 pushTreeFork(returnFiber, numberOfForks); 13641 } 13642 13643 return resultingFirstChild; 13644 } 13645 13646 if (oldFiber === null) { 13647 // If we don't have any more existing children we can choose a fast path 13648 // since the rest will all be insertions. 13649 for (; newIdx < newChildren.length; newIdx++) { 13650 var _newFiber = createChild(returnFiber, newChildren[newIdx], lanes); 13651 13652 if (_newFiber === null) { 13653 continue; 13654 } 13655 13656 lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); 13657 13658 if (previousNewFiber === null) { 13659 // TODO: Move out of the loop. This only happens for the first run. 13660 resultingFirstChild = _newFiber; 13661 } else { 13662 previousNewFiber.sibling = _newFiber; 13663 } 13664 13665 previousNewFiber = _newFiber; 13666 } 13667 13668 if (getIsHydrating()) { 13669 var _numberOfForks = newIdx; 13670 pushTreeFork(returnFiber, _numberOfForks); 13671 } 13672 13673 return resultingFirstChild; 13674 } // Add all children to a key map for quick lookups. 13675 13676 13677 var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. 13678 13679 for (; newIdx < newChildren.length; newIdx++) { 13680 var _newFiber2 = updateFromMap(existingChildren, returnFiber, newIdx, newChildren[newIdx], lanes); 13681 13682 if (_newFiber2 !== null) { 13683 if (shouldTrackSideEffects) { 13684 if (_newFiber2.alternate !== null) { 13685 // The new fiber is a work in progress, but if there exists a 13686 // current, that means that we reused the fiber. We need to delete 13687 // it from the child list so that we don't add it to the deletion 13688 // list. 13689 existingChildren.delete(_newFiber2.key === null ? newIdx : _newFiber2.key); 13690 } 13691 } 13692 13693 lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); 13694 13695 if (previousNewFiber === null) { 13696 resultingFirstChild = _newFiber2; 13697 } else { 13698 previousNewFiber.sibling = _newFiber2; 13699 } 13700 13701 previousNewFiber = _newFiber2; 13702 } 13703 } 13704 13705 if (shouldTrackSideEffects) { 13706 // Any existing children that weren't consumed above were deleted. We need 13707 // to add them to the deletion list. 13708 existingChildren.forEach(function (child) { 13709 return deleteChild(returnFiber, child); 13710 }); 13711 } 13712 13713 if (getIsHydrating()) { 13714 var _numberOfForks2 = newIdx; 13715 pushTreeFork(returnFiber, _numberOfForks2); 13716 } 13717 13718 return resultingFirstChild; 13719 } 13720 13721 function reconcileChildrenIterator(returnFiber, currentFirstChild, newChildrenIterable, lanes) { 13722 // This is the same implementation as reconcileChildrenArray(), 13723 // but using the iterator instead. 13724 var iteratorFn = getIteratorFn(newChildrenIterable); 13725 13726 if (typeof iteratorFn !== 'function') { 13727 throw new Error('An object is not an iterable. This error is likely caused by a bug in ' + 'React. Please file an issue.'); 13728 } 13729 13730 { 13731 // We don't support rendering Generators because it's a mutation. 13732 // See https://github.com/facebook/react/issues/12995 13733 if (typeof Symbol === 'function' && // $FlowFixMe Flow doesn't know about toStringTag 13734 newChildrenIterable[Symbol.toStringTag] === 'Generator') { 13735 if (!didWarnAboutGenerators) { 13736 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.'); 13737 } 13738 13739 didWarnAboutGenerators = true; 13740 } // Warn about using Maps as children 13741 13742 13743 if (newChildrenIterable.entries === iteratorFn) { 13744 if (!didWarnAboutMaps) { 13745 error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); 13746 } 13747 13748 didWarnAboutMaps = true; 13749 } // First, validate keys. 13750 // We'll get a different iterator later for the main pass. 13751 13752 13753 var _newChildren = iteratorFn.call(newChildrenIterable); 13754 13755 if (_newChildren) { 13756 var knownKeys = null; 13757 13758 var _step = _newChildren.next(); 13759 13760 for (; !_step.done; _step = _newChildren.next()) { 13761 var child = _step.value; 13762 knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); 13763 } 13764 } 13765 } 13766 13767 var newChildren = iteratorFn.call(newChildrenIterable); 13768 13769 if (newChildren == null) { 13770 throw new Error('An iterable object provided no iterator.'); 13771 } 13772 13773 var resultingFirstChild = null; 13774 var previousNewFiber = null; 13775 var oldFiber = currentFirstChild; 13776 var lastPlacedIndex = 0; 13777 var newIdx = 0; 13778 var nextOldFiber = null; 13779 var step = newChildren.next(); 13780 13781 for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) { 13782 if (oldFiber.index > newIdx) { 13783 nextOldFiber = oldFiber; 13784 oldFiber = null; 13785 } else { 13786 nextOldFiber = oldFiber.sibling; 13787 } 13788 13789 var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); 13790 13791 if (newFiber === null) { 13792 // TODO: This breaks on empty slots like null children. That's 13793 // unfortunate because it triggers the slow path all the time. We need 13794 // a better way to communicate whether this was a miss or null, 13795 // boolean, undefined, etc. 13796 if (oldFiber === null) { 13797 oldFiber = nextOldFiber; 13798 } 13799 13800 break; 13801 } 13802 13803 if (shouldTrackSideEffects) { 13804 if (oldFiber && newFiber.alternate === null) { 13805 // We matched the slot, but we didn't reuse the existing fiber, so we 13806 // need to delete the existing child. 13807 deleteChild(returnFiber, oldFiber); 13808 } 13809 } 13810 13811 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); 13812 13813 if (previousNewFiber === null) { 13814 // TODO: Move out of the loop. This only happens for the first run. 13815 resultingFirstChild = newFiber; 13816 } else { 13817 // TODO: Defer siblings if we're not at the right index for this slot. 13818 // I.e. if we had null values before, then we want to defer this 13819 // for each null value. However, we also don't want to call updateSlot 13820 // with the previous one. 13821 previousNewFiber.sibling = newFiber; 13822 } 13823 13824 previousNewFiber = newFiber; 13825 oldFiber = nextOldFiber; 13826 } 13827 13828 if (step.done) { 13829 // We've reached the end of the new children. We can delete the rest. 13830 deleteRemainingChildren(returnFiber, oldFiber); 13831 13832 if (getIsHydrating()) { 13833 var numberOfForks = newIdx; 13834 pushTreeFork(returnFiber, numberOfForks); 13835 } 13836 13837 return resultingFirstChild; 13838 } 13839 13840 if (oldFiber === null) { 13841 // If we don't have any more existing children we can choose a fast path 13842 // since the rest will all be insertions. 13843 for (; !step.done; newIdx++, step = newChildren.next()) { 13844 var _newFiber3 = createChild(returnFiber, step.value, lanes); 13845 13846 if (_newFiber3 === null) { 13847 continue; 13848 } 13849 13850 lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); 13851 13852 if (previousNewFiber === null) { 13853 // TODO: Move out of the loop. This only happens for the first run. 13854 resultingFirstChild = _newFiber3; 13855 } else { 13856 previousNewFiber.sibling = _newFiber3; 13857 } 13858 13859 previousNewFiber = _newFiber3; 13860 } 13861 13862 if (getIsHydrating()) { 13863 var _numberOfForks3 = newIdx; 13864 pushTreeFork(returnFiber, _numberOfForks3); 13865 } 13866 13867 return resultingFirstChild; 13868 } // Add all children to a key map for quick lookups. 13869 13870 13871 var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. 13872 13873 for (; !step.done; newIdx++, step = newChildren.next()) { 13874 var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, lanes); 13875 13876 if (_newFiber4 !== null) { 13877 if (shouldTrackSideEffects) { 13878 if (_newFiber4.alternate !== null) { 13879 // The new fiber is a work in progress, but if there exists a 13880 // current, that means that we reused the fiber. We need to delete 13881 // it from the child list so that we don't add it to the deletion 13882 // list. 13883 existingChildren.delete(_newFiber4.key === null ? newIdx : _newFiber4.key); 13884 } 13885 } 13886 13887 lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); 13888 13889 if (previousNewFiber === null) { 13890 resultingFirstChild = _newFiber4; 13891 } else { 13892 previousNewFiber.sibling = _newFiber4; 13893 } 13894 13895 previousNewFiber = _newFiber4; 13896 } 13897 } 13898 13899 if (shouldTrackSideEffects) { 13900 // Any existing children that weren't consumed above were deleted. We need 13901 // to add them to the deletion list. 13902 existingChildren.forEach(function (child) { 13903 return deleteChild(returnFiber, child); 13904 }); 13905 } 13906 13907 if (getIsHydrating()) { 13908 var _numberOfForks4 = newIdx; 13909 pushTreeFork(returnFiber, _numberOfForks4); 13910 } 13911 13912 return resultingFirstChild; 13913 } 13914 13915 function reconcileSingleTextNode(returnFiber, currentFirstChild, textContent, lanes) { 13916 // There's no need to check for keys on text nodes since we don't have a 13917 // way to define them. 13918 if (currentFirstChild !== null && currentFirstChild.tag === HostText) { 13919 // We already have an existing node so let's just update it and delete 13920 // the rest. 13921 deleteRemainingChildren(returnFiber, currentFirstChild.sibling); 13922 var existing = useFiber(currentFirstChild, textContent); 13923 existing.return = returnFiber; 13924 return existing; 13925 } // The existing first child is not a text node so we need to create one 13926 // and delete the existing ones. 13927 13928 13929 deleteRemainingChildren(returnFiber, currentFirstChild); 13930 var created = createFiberFromText(textContent, returnFiber.mode, lanes); 13931 created.return = returnFiber; 13932 return created; 13933 } 13934 13935 function reconcileSingleElement(returnFiber, currentFirstChild, element, lanes) { 13936 var key = element.key; 13937 var child = currentFirstChild; 13938 13939 while (child !== null) { 13940 // TODO: If key === null and child.key === null, then this only applies to 13941 // the first item in the list. 13942 if (child.key === key) { 13943 var elementType = element.type; 13944 13945 if (elementType === REACT_FRAGMENT_TYPE) { 13946 if (child.tag === Fragment) { 13947 deleteRemainingChildren(returnFiber, child.sibling); 13948 var existing = useFiber(child, element.props.children); 13949 existing.return = returnFiber; 13950 13951 { 13952 existing._debugSource = element._source; 13953 existing._debugOwner = element._owner; 13954 } 13955 13956 return existing; 13957 } 13958 } else { 13959 if (child.elementType === elementType || ( // Keep this check inline so it only runs on the false path: 13960 isCompatibleFamilyForHotReloading(child, element) ) || // Lazy types should reconcile their resolved type. 13961 // We need to do this after the Hot Reloading check above, 13962 // because hot reloading has different semantics than prod because 13963 // it doesn't resuspend. So we can't let the call below suspend. 13964 typeof elementType === 'object' && elementType !== null && elementType.$$typeof === REACT_LAZY_TYPE && resolveLazy(elementType) === child.type) { 13965 deleteRemainingChildren(returnFiber, child.sibling); 13966 13967 var _existing = useFiber(child, element.props); 13968 13969 _existing.ref = coerceRef(returnFiber, child, element); 13970 _existing.return = returnFiber; 13971 13972 { 13973 _existing._debugSource = element._source; 13974 _existing._debugOwner = element._owner; 13975 } 13976 13977 return _existing; 13978 } 13979 } // Didn't match. 13980 13981 13982 deleteRemainingChildren(returnFiber, child); 13983 break; 13984 } else { 13985 deleteChild(returnFiber, child); 13986 } 13987 13988 child = child.sibling; 13989 } 13990 13991 if (element.type === REACT_FRAGMENT_TYPE) { 13992 var created = createFiberFromFragment(element.props.children, returnFiber.mode, lanes, element.key); 13993 created.return = returnFiber; 13994 return created; 13995 } else { 13996 var _created4 = createFiberFromElement(element, returnFiber.mode, lanes); 13997 13998 _created4.ref = coerceRef(returnFiber, currentFirstChild, element); 13999 _created4.return = returnFiber; 14000 return _created4; 14001 } 14002 } 14003 14004 function reconcileSinglePortal(returnFiber, currentFirstChild, portal, lanes) { 14005 var key = portal.key; 14006 var child = currentFirstChild; 14007 14008 while (child !== null) { 14009 // TODO: If key === null and child.key === null, then this only applies to 14010 // the first item in the list. 14011 if (child.key === key) { 14012 if (child.tag === HostPortal && child.stateNode.containerInfo === portal.containerInfo && child.stateNode.implementation === portal.implementation) { 14013 deleteRemainingChildren(returnFiber, child.sibling); 14014 var existing = useFiber(child, portal.children || []); 14015 existing.return = returnFiber; 14016 return existing; 14017 } else { 14018 deleteRemainingChildren(returnFiber, child); 14019 break; 14020 } 14021 } else { 14022 deleteChild(returnFiber, child); 14023 } 14024 14025 child = child.sibling; 14026 } 14027 14028 var created = createFiberFromPortal(portal, returnFiber.mode, lanes); 14029 created.return = returnFiber; 14030 return created; 14031 } // This API will tag the children with the side-effect of the reconciliation 14032 // itself. They will be added to the side-effect list as we pass through the 14033 // children and the parent. 14034 14035 14036 function reconcileChildFibers(returnFiber, currentFirstChild, newChild, lanes) { 14037 // This function is not recursive. 14038 // If the top level item is an array, we treat it as a set of children, 14039 // not as a fragment. Nested arrays on the other hand will be treated as 14040 // fragment nodes. Recursion happens at the normal flow. 14041 // Handle top level unkeyed fragments as if they were arrays. 14042 // This leads to an ambiguity between <>{[...]}</> and <>...</>. 14043 // We treat the ambiguous cases above the same. 14044 var isUnkeyedTopLevelFragment = typeof newChild === 'object' && newChild !== null && newChild.type === REACT_FRAGMENT_TYPE && newChild.key === null; 14045 14046 if (isUnkeyedTopLevelFragment) { 14047 newChild = newChild.props.children; 14048 } // Handle object types 14049 14050 14051 if (typeof newChild === 'object' && newChild !== null) { 14052 switch (newChild.$$typeof) { 14053 case REACT_ELEMENT_TYPE: 14054 return placeSingleChild(reconcileSingleElement(returnFiber, currentFirstChild, newChild, lanes)); 14055 14056 case REACT_PORTAL_TYPE: 14057 return placeSingleChild(reconcileSinglePortal(returnFiber, currentFirstChild, newChild, lanes)); 14058 14059 case REACT_LAZY_TYPE: 14060 var payload = newChild._payload; 14061 var init = newChild._init; // TODO: This function is supposed to be non-recursive. 14062 14063 return reconcileChildFibers(returnFiber, currentFirstChild, init(payload), lanes); 14064 } 14065 14066 if (isArray(newChild)) { 14067 return reconcileChildrenArray(returnFiber, currentFirstChild, newChild, lanes); 14068 } 14069 14070 if (getIteratorFn(newChild)) { 14071 return reconcileChildrenIterator(returnFiber, currentFirstChild, newChild, lanes); 14072 } 14073 14074 throwOnInvalidObjectType(returnFiber, newChild); 14075 } 14076 14077 if (typeof newChild === 'string' && newChild !== '' || typeof newChild === 'number') { 14078 return placeSingleChild(reconcileSingleTextNode(returnFiber, currentFirstChild, '' + newChild, lanes)); 14079 } 14080 14081 { 14082 if (typeof newChild === 'function') { 14083 warnOnFunctionType(returnFiber); 14084 } 14085 } // Remaining cases are all treated as empty. 14086 14087 14088 return deleteRemainingChildren(returnFiber, currentFirstChild); 14089 } 14090 14091 return reconcileChildFibers; 14092 } 14093 14094 var reconcileChildFibers = ChildReconciler(true); 14095 var mountChildFibers = ChildReconciler(false); 14096 function cloneChildFibers(current, workInProgress) { 14097 if (current !== null && workInProgress.child !== current.child) { 14098 throw new Error('Resuming work not yet implemented.'); 14099 } 14100 14101 if (workInProgress.child === null) { 14102 return; 14103 } 14104 14105 var currentChild = workInProgress.child; 14106 var newChild = createWorkInProgress(currentChild, currentChild.pendingProps); 14107 workInProgress.child = newChild; 14108 newChild.return = workInProgress; 14109 14110 while (currentChild.sibling !== null) { 14111 currentChild = currentChild.sibling; 14112 newChild = newChild.sibling = createWorkInProgress(currentChild, currentChild.pendingProps); 14113 newChild.return = workInProgress; 14114 } 14115 14116 newChild.sibling = null; 14117 } // Reset a workInProgress child set to prepare it for a second pass. 14118 14119 function resetChildFibers(workInProgress, lanes) { 14120 var child = workInProgress.child; 14121 14122 while (child !== null) { 14123 resetWorkInProgress(child, lanes); 14124 child = child.sibling; 14125 } 14126 } 14127 14128 var valueCursor = createCursor(null); 14129 var rendererSigil; 14130 14131 { 14132 // Use this to detect multiple renderers using the same context 14133 rendererSigil = {}; 14134 } 14135 14136 var currentlyRenderingFiber = null; 14137 var lastContextDependency = null; 14138 var lastFullyObservedContext = null; 14139 var isDisallowedContextReadInDEV = false; 14140 function resetContextDependencies() { 14141 // This is called right before React yields execution, to ensure `readContext` 14142 // cannot be called outside the render phase. 14143 currentlyRenderingFiber = null; 14144 lastContextDependency = null; 14145 lastFullyObservedContext = null; 14146 14147 { 14148 isDisallowedContextReadInDEV = false; 14149 } 14150 } 14151 function enterDisallowedContextReadInDEV() { 14152 { 14153 isDisallowedContextReadInDEV = true; 14154 } 14155 } 14156 function exitDisallowedContextReadInDEV() { 14157 { 14158 isDisallowedContextReadInDEV = false; 14159 } 14160 } 14161 function pushProvider(providerFiber, context, nextValue) { 14162 { 14163 push(valueCursor, context._currentValue, providerFiber); 14164 context._currentValue = nextValue; 14165 14166 { 14167 if (context._currentRenderer !== undefined && context._currentRenderer !== null && context._currentRenderer !== rendererSigil) { 14168 error('Detected multiple renderers concurrently rendering the ' + 'same context provider. This is currently unsupported.'); 14169 } 14170 14171 context._currentRenderer = rendererSigil; 14172 } 14173 } 14174 } 14175 function popProvider(context, providerFiber) { 14176 var currentValue = valueCursor.current; 14177 pop(valueCursor, providerFiber); 14178 14179 { 14180 { 14181 context._currentValue = currentValue; 14182 } 14183 } 14184 } 14185 function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { 14186 // Update the child lanes of all the ancestors, including the alternates. 14187 var node = parent; 14188 14189 while (node !== null) { 14190 var alternate = node.alternate; 14191 14192 if (!isSubsetOfLanes(node.childLanes, renderLanes)) { 14193 node.childLanes = mergeLanes(node.childLanes, renderLanes); 14194 14195 if (alternate !== null) { 14196 alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); 14197 } 14198 } else if (alternate !== null && !isSubsetOfLanes(alternate.childLanes, renderLanes)) { 14199 alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); 14200 } 14201 14202 if (node === propagationRoot) { 14203 break; 14204 } 14205 14206 node = node.return; 14207 } 14208 14209 { 14210 if (node !== propagationRoot) { 14211 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.'); 14212 } 14213 } 14214 } 14215 function propagateContextChange(workInProgress, context, renderLanes) { 14216 { 14217 propagateContextChange_eager(workInProgress, context, renderLanes); 14218 } 14219 } 14220 14221 function propagateContextChange_eager(workInProgress, context, renderLanes) { 14222 14223 var fiber = workInProgress.child; 14224 14225 if (fiber !== null) { 14226 // Set the return pointer of the child to the work-in-progress fiber. 14227 fiber.return = workInProgress; 14228 } 14229 14230 while (fiber !== null) { 14231 var nextFiber = void 0; // Visit this fiber. 14232 14233 var list = fiber.dependencies; 14234 14235 if (list !== null) { 14236 nextFiber = fiber.child; 14237 var dependency = list.firstContext; 14238 14239 while (dependency !== null) { 14240 // Check if the context matches. 14241 if (dependency.context === context) { 14242 // Match! Schedule an update on this fiber. 14243 if (fiber.tag === ClassComponent) { 14244 // Schedule a force update on the work-in-progress. 14245 var lane = pickArbitraryLane(renderLanes); 14246 var update = createUpdate(NoTimestamp, lane); 14247 update.tag = ForceUpdate; // TODO: Because we don't have a work-in-progress, this will add the 14248 // update to the current fiber, too, which means it will persist even if 14249 // this render is thrown away. Since it's a race condition, not sure it's 14250 // worth fixing. 14251 // Inlined `enqueueUpdate` to remove interleaved update check 14252 14253 var updateQueue = fiber.updateQueue; 14254 14255 if (updateQueue === null) ; else { 14256 var sharedQueue = updateQueue.shared; 14257 var pending = sharedQueue.pending; 14258 14259 if (pending === null) { 14260 // This is the first update. Create a circular list. 14261 update.next = update; 14262 } else { 14263 update.next = pending.next; 14264 pending.next = update; 14265 } 14266 14267 sharedQueue.pending = update; 14268 } 14269 } 14270 14271 fiber.lanes = mergeLanes(fiber.lanes, renderLanes); 14272 var alternate = fiber.alternate; 14273 14274 if (alternate !== null) { 14275 alternate.lanes = mergeLanes(alternate.lanes, renderLanes); 14276 } 14277 14278 scheduleContextWorkOnParentPath(fiber.return, renderLanes, workInProgress); // Mark the updated lanes on the list, too. 14279 14280 list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the 14281 // dependency list. 14282 14283 break; 14284 } 14285 14286 dependency = dependency.next; 14287 } 14288 } else if (fiber.tag === ContextProvider) { 14289 // Don't scan deeper if this is a matching provider 14290 nextFiber = fiber.type === workInProgress.type ? null : fiber.child; 14291 } else if (fiber.tag === DehydratedFragment) { 14292 // If a dehydrated suspense boundary is in this subtree, we don't know 14293 // if it will have any context consumers in it. The best we can do is 14294 // mark it as having updates. 14295 var parentSuspense = fiber.return; 14296 14297 if (parentSuspense === null) { 14298 throw new Error('We just came from a parent so we must have had a parent. This is a bug in React.'); 14299 } 14300 14301 parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); 14302 var _alternate = parentSuspense.alternate; 14303 14304 if (_alternate !== null) { 14305 _alternate.lanes = mergeLanes(_alternate.lanes, renderLanes); 14306 } // This is intentionally passing this fiber as the parent 14307 // because we want to schedule this fiber as having work 14308 // on its children. We'll use the childLanes on 14309 // this fiber to indicate that a context has changed. 14310 14311 14312 scheduleContextWorkOnParentPath(parentSuspense, renderLanes, workInProgress); 14313 nextFiber = fiber.sibling; 14314 } else { 14315 // Traverse down. 14316 nextFiber = fiber.child; 14317 } 14318 14319 if (nextFiber !== null) { 14320 // Set the return pointer of the child to the work-in-progress fiber. 14321 nextFiber.return = fiber; 14322 } else { 14323 // No child. Traverse to next sibling. 14324 nextFiber = fiber; 14325 14326 while (nextFiber !== null) { 14327 if (nextFiber === workInProgress) { 14328 // We're back to the root of this subtree. Exit. 14329 nextFiber = null; 14330 break; 14331 } 14332 14333 var sibling = nextFiber.sibling; 14334 14335 if (sibling !== null) { 14336 // Set the return pointer of the sibling to the work-in-progress fiber. 14337 sibling.return = nextFiber.return; 14338 nextFiber = sibling; 14339 break; 14340 } // No more siblings. Traverse up. 14341 14342 14343 nextFiber = nextFiber.return; 14344 } 14345 } 14346 14347 fiber = nextFiber; 14348 } 14349 } 14350 function prepareToReadContext(workInProgress, renderLanes) { 14351 currentlyRenderingFiber = workInProgress; 14352 lastContextDependency = null; 14353 lastFullyObservedContext = null; 14354 var dependencies = workInProgress.dependencies; 14355 14356 if (dependencies !== null) { 14357 { 14358 var firstContext = dependencies.firstContext; 14359 14360 if (firstContext !== null) { 14361 if (includesSomeLane(dependencies.lanes, renderLanes)) { 14362 // Context list has a pending update. Mark that this fiber performed work. 14363 markWorkInProgressReceivedUpdate(); 14364 } // Reset the work-in-progress list 14365 14366 14367 dependencies.firstContext = null; 14368 } 14369 } 14370 } 14371 } 14372 function readContext(context) { 14373 { 14374 // This warning would fire if you read context inside a Hook like useMemo. 14375 // Unlike the class check below, it's not enforced in production for perf. 14376 if (isDisallowedContextReadInDEV) { 14377 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().'); 14378 } 14379 } 14380 14381 var value = context._currentValue ; 14382 14383 if (lastFullyObservedContext === context) ; else { 14384 var contextItem = { 14385 context: context, 14386 memoizedValue: value, 14387 next: null 14388 }; 14389 14390 if (lastContextDependency === null) { 14391 if (currentlyRenderingFiber === null) { 14392 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().'); 14393 } // This is the first dependency for this component. Create a new list. 14394 14395 14396 lastContextDependency = contextItem; 14397 currentlyRenderingFiber.dependencies = { 14398 lanes: NoLanes, 14399 firstContext: contextItem 14400 }; 14401 } else { 14402 // Append a new context item. 14403 lastContextDependency = lastContextDependency.next = contextItem; 14404 } 14405 } 14406 14407 return value; 14408 } 14409 14410 // render. When this render exits, either because it finishes or because it is 14411 // interrupted, the interleaved updates will be transferred onto the main part 14412 // of the queue. 14413 14414 var concurrentQueues = null; 14415 function pushConcurrentUpdateQueue(queue) { 14416 if (concurrentQueues === null) { 14417 concurrentQueues = [queue]; 14418 } else { 14419 concurrentQueues.push(queue); 14420 } 14421 } 14422 function finishQueueingConcurrentUpdates() { 14423 // Transfer the interleaved updates onto the main queue. Each queue has a 14424 // `pending` field and an `interleaved` field. When they are not null, they 14425 // point to the last node in a circular linked list. We need to append the 14426 // interleaved list to the end of the pending list by joining them into a 14427 // single, circular list. 14428 if (concurrentQueues !== null) { 14429 for (var i = 0; i < concurrentQueues.length; i++) { 14430 var queue = concurrentQueues[i]; 14431 var lastInterleavedUpdate = queue.interleaved; 14432 14433 if (lastInterleavedUpdate !== null) { 14434 queue.interleaved = null; 14435 var firstInterleavedUpdate = lastInterleavedUpdate.next; 14436 var lastPendingUpdate = queue.pending; 14437 14438 if (lastPendingUpdate !== null) { 14439 var firstPendingUpdate = lastPendingUpdate.next; 14440 lastPendingUpdate.next = firstInterleavedUpdate; 14441 lastInterleavedUpdate.next = firstPendingUpdate; 14442 } 14443 14444 queue.pending = lastInterleavedUpdate; 14445 } 14446 } 14447 14448 concurrentQueues = null; 14449 } 14450 } 14451 function enqueueConcurrentHookUpdate(fiber, queue, update, lane) { 14452 var interleaved = queue.interleaved; 14453 14454 if (interleaved === null) { 14455 // This is the first update. Create a circular list. 14456 update.next = update; // At the end of the current render, this queue's interleaved updates will 14457 // be transferred to the pending queue. 14458 14459 pushConcurrentUpdateQueue(queue); 14460 } else { 14461 update.next = interleaved.next; 14462 interleaved.next = update; 14463 } 14464 14465 queue.interleaved = update; 14466 return markUpdateLaneFromFiberToRoot(fiber, lane); 14467 } 14468 function enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update, lane) { 14469 var interleaved = queue.interleaved; 14470 14471 if (interleaved === null) { 14472 // This is the first update. Create a circular list. 14473 update.next = update; // At the end of the current render, this queue's interleaved updates will 14474 // be transferred to the pending queue. 14475 14476 pushConcurrentUpdateQueue(queue); 14477 } else { 14478 update.next = interleaved.next; 14479 interleaved.next = update; 14480 } 14481 14482 queue.interleaved = update; 14483 } 14484 function enqueueConcurrentClassUpdate(fiber, queue, update, lane) { 14485 var interleaved = queue.interleaved; 14486 14487 if (interleaved === null) { 14488 // This is the first update. Create a circular list. 14489 update.next = update; // At the end of the current render, this queue's interleaved updates will 14490 // be transferred to the pending queue. 14491 14492 pushConcurrentUpdateQueue(queue); 14493 } else { 14494 update.next = interleaved.next; 14495 interleaved.next = update; 14496 } 14497 14498 queue.interleaved = update; 14499 return markUpdateLaneFromFiberToRoot(fiber, lane); 14500 } 14501 function enqueueConcurrentRenderForLane(fiber, lane) { 14502 return markUpdateLaneFromFiberToRoot(fiber, lane); 14503 } // Calling this function outside this module should only be done for backwards 14504 // compatibility and should always be accompanied by a warning. 14505 14506 var unsafe_markUpdateLaneFromFiberToRoot = markUpdateLaneFromFiberToRoot; 14507 14508 function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { 14509 // Update the source fiber's lanes 14510 sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane); 14511 var alternate = sourceFiber.alternate; 14512 14513 if (alternate !== null) { 14514 alternate.lanes = mergeLanes(alternate.lanes, lane); 14515 } 14516 14517 { 14518 if (alternate === null && (sourceFiber.flags & (Placement | Hydrating)) !== NoFlags) { 14519 warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); 14520 } 14521 } // Walk the parent path to the root and update the child lanes. 14522 14523 14524 var node = sourceFiber; 14525 var parent = sourceFiber.return; 14526 14527 while (parent !== null) { 14528 parent.childLanes = mergeLanes(parent.childLanes, lane); 14529 alternate = parent.alternate; 14530 14531 if (alternate !== null) { 14532 alternate.childLanes = mergeLanes(alternate.childLanes, lane); 14533 } else { 14534 { 14535 if ((parent.flags & (Placement | Hydrating)) !== NoFlags) { 14536 warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); 14537 } 14538 } 14539 } 14540 14541 node = parent; 14542 parent = parent.return; 14543 } 14544 14545 if (node.tag === HostRoot) { 14546 var root = node.stateNode; 14547 return root; 14548 } else { 14549 return null; 14550 } 14551 } 14552 14553 var UpdateState = 0; 14554 var ReplaceState = 1; 14555 var ForceUpdate = 2; 14556 var CaptureUpdate = 3; // Global state that is reset at the beginning of calling `processUpdateQueue`. 14557 // It should only be read right after calling `processUpdateQueue`, via 14558 // `checkHasForceUpdateAfterProcessing`. 14559 14560 var hasForceUpdate = false; 14561 var didWarnUpdateInsideUpdate; 14562 var currentlyProcessingQueue; 14563 14564 { 14565 didWarnUpdateInsideUpdate = false; 14566 currentlyProcessingQueue = null; 14567 } 14568 14569 function initializeUpdateQueue(fiber) { 14570 var queue = { 14571 baseState: fiber.memoizedState, 14572 firstBaseUpdate: null, 14573 lastBaseUpdate: null, 14574 shared: { 14575 pending: null, 14576 interleaved: null, 14577 lanes: NoLanes 14578 }, 14579 effects: null 14580 }; 14581 fiber.updateQueue = queue; 14582 } 14583 function cloneUpdateQueue(current, workInProgress) { 14584 // Clone the update queue from current. Unless it's already a clone. 14585 var queue = workInProgress.updateQueue; 14586 var currentQueue = current.updateQueue; 14587 14588 if (queue === currentQueue) { 14589 var clone = { 14590 baseState: currentQueue.baseState, 14591 firstBaseUpdate: currentQueue.firstBaseUpdate, 14592 lastBaseUpdate: currentQueue.lastBaseUpdate, 14593 shared: currentQueue.shared, 14594 effects: currentQueue.effects 14595 }; 14596 workInProgress.updateQueue = clone; 14597 } 14598 } 14599 function createUpdate(eventTime, lane) { 14600 var update = { 14601 eventTime: eventTime, 14602 lane: lane, 14603 tag: UpdateState, 14604 payload: null, 14605 callback: null, 14606 next: null 14607 }; 14608 return update; 14609 } 14610 function enqueueUpdate(fiber, update, lane) { 14611 var updateQueue = fiber.updateQueue; 14612 14613 if (updateQueue === null) { 14614 // Only occurs if the fiber has been unmounted. 14615 return null; 14616 } 14617 14618 var sharedQueue = updateQueue.shared; 14619 14620 { 14621 if (currentlyProcessingQueue === sharedQueue && !didWarnUpdateInsideUpdate) { 14622 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.'); 14623 14624 didWarnUpdateInsideUpdate = true; 14625 } 14626 } 14627 14628 if (isUnsafeClassRenderPhaseUpdate()) { 14629 // This is an unsafe render phase update. Add directly to the update 14630 // queue so we can process it immediately during the current render. 14631 var pending = sharedQueue.pending; 14632 14633 if (pending === null) { 14634 // This is the first update. Create a circular list. 14635 update.next = update; 14636 } else { 14637 update.next = pending.next; 14638 pending.next = update; 14639 } 14640 14641 sharedQueue.pending = update; // Update the childLanes even though we're most likely already rendering 14642 // this fiber. This is for backwards compatibility in the case where you 14643 // update a different component during render phase than the one that is 14644 // currently renderings (a pattern that is accompanied by a warning). 14645 14646 return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); 14647 } else { 14648 return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); 14649 } 14650 } 14651 function entangleTransitions(root, fiber, lane) { 14652 var updateQueue = fiber.updateQueue; 14653 14654 if (updateQueue === null) { 14655 // Only occurs if the fiber has been unmounted. 14656 return; 14657 } 14658 14659 var sharedQueue = updateQueue.shared; 14660 14661 if (isTransitionLane(lane)) { 14662 var queueLanes = sharedQueue.lanes; // If any entangled lanes are no longer pending on the root, then they must 14663 // have finished. We can remove them from the shared queue, which represents 14664 // a superset of the actually pending lanes. In some cases we may entangle 14665 // more than we need to, but that's OK. In fact it's worse if we *don't* 14666 // entangle when we should. 14667 14668 queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. 14669 14670 var newQueueLanes = mergeLanes(queueLanes, lane); 14671 sharedQueue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if 14672 // the lane finished since the last time we entangled it. So we need to 14673 // entangle it again, just to be sure. 14674 14675 markRootEntangled(root, newQueueLanes); 14676 } 14677 } 14678 function enqueueCapturedUpdate(workInProgress, capturedUpdate) { 14679 // Captured updates are updates that are thrown by a child during the render 14680 // phase. They should be discarded if the render is aborted. Therefore, 14681 // we should only put them on the work-in-progress queue, not the current one. 14682 var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone. 14683 14684 var current = workInProgress.alternate; 14685 14686 if (current !== null) { 14687 var currentQueue = current.updateQueue; 14688 14689 if (queue === currentQueue) { 14690 // The work-in-progress queue is the same as current. This happens when 14691 // we bail out on a parent fiber that then captures an error thrown by 14692 // a child. Since we want to append the update only to the work-in 14693 // -progress queue, we need to clone the updates. We usually clone during 14694 // processUpdateQueue, but that didn't happen in this case because we 14695 // skipped over the parent when we bailed out. 14696 var newFirst = null; 14697 var newLast = null; 14698 var firstBaseUpdate = queue.firstBaseUpdate; 14699 14700 if (firstBaseUpdate !== null) { 14701 // Loop through the updates and clone them. 14702 var update = firstBaseUpdate; 14703 14704 do { 14705 var clone = { 14706 eventTime: update.eventTime, 14707 lane: update.lane, 14708 tag: update.tag, 14709 payload: update.payload, 14710 callback: update.callback, 14711 next: null 14712 }; 14713 14714 if (newLast === null) { 14715 newFirst = newLast = clone; 14716 } else { 14717 newLast.next = clone; 14718 newLast = clone; 14719 } 14720 14721 update = update.next; 14722 } while (update !== null); // Append the captured update the end of the cloned list. 14723 14724 14725 if (newLast === null) { 14726 newFirst = newLast = capturedUpdate; 14727 } else { 14728 newLast.next = capturedUpdate; 14729 newLast = capturedUpdate; 14730 } 14731 } else { 14732 // There are no base updates. 14733 newFirst = newLast = capturedUpdate; 14734 } 14735 14736 queue = { 14737 baseState: currentQueue.baseState, 14738 firstBaseUpdate: newFirst, 14739 lastBaseUpdate: newLast, 14740 shared: currentQueue.shared, 14741 effects: currentQueue.effects 14742 }; 14743 workInProgress.updateQueue = queue; 14744 return; 14745 } 14746 } // Append the update to the end of the list. 14747 14748 14749 var lastBaseUpdate = queue.lastBaseUpdate; 14750 14751 if (lastBaseUpdate === null) { 14752 queue.firstBaseUpdate = capturedUpdate; 14753 } else { 14754 lastBaseUpdate.next = capturedUpdate; 14755 } 14756 14757 queue.lastBaseUpdate = capturedUpdate; 14758 } 14759 14760 function getStateFromUpdate(workInProgress, queue, update, prevState, nextProps, instance) { 14761 switch (update.tag) { 14762 case ReplaceState: 14763 { 14764 var payload = update.payload; 14765 14766 if (typeof payload === 'function') { 14767 // Updater function 14768 { 14769 enterDisallowedContextReadInDEV(); 14770 } 14771 14772 var nextState = payload.call(instance, prevState, nextProps); 14773 14774 { 14775 if ( workInProgress.mode & StrictLegacyMode) { 14776 setIsStrictModeForDevtools(true); 14777 14778 try { 14779 payload.call(instance, prevState, nextProps); 14780 } finally { 14781 setIsStrictModeForDevtools(false); 14782 } 14783 } 14784 14785 exitDisallowedContextReadInDEV(); 14786 } 14787 14788 return nextState; 14789 } // State object 14790 14791 14792 return payload; 14793 } 14794 14795 case CaptureUpdate: 14796 { 14797 workInProgress.flags = workInProgress.flags & ~ShouldCapture | DidCapture; 14798 } 14799 // Intentional fallthrough 14800 14801 case UpdateState: 14802 { 14803 var _payload = update.payload; 14804 var partialState; 14805 14806 if (typeof _payload === 'function') { 14807 // Updater function 14808 { 14809 enterDisallowedContextReadInDEV(); 14810 } 14811 14812 partialState = _payload.call(instance, prevState, nextProps); 14813 14814 { 14815 if ( workInProgress.mode & StrictLegacyMode) { 14816 setIsStrictModeForDevtools(true); 14817 14818 try { 14819 _payload.call(instance, prevState, nextProps); 14820 } finally { 14821 setIsStrictModeForDevtools(false); 14822 } 14823 } 14824 14825 exitDisallowedContextReadInDEV(); 14826 } 14827 } else { 14828 // Partial state object 14829 partialState = _payload; 14830 } 14831 14832 if (partialState === null || partialState === undefined) { 14833 // Null and undefined are treated as no-ops. 14834 return prevState; 14835 } // Merge the partial state and the previous state. 14836 14837 14838 return assign({}, prevState, partialState); 14839 } 14840 14841 case ForceUpdate: 14842 { 14843 hasForceUpdate = true; 14844 return prevState; 14845 } 14846 } 14847 14848 return prevState; 14849 } 14850 14851 function processUpdateQueue(workInProgress, props, instance, renderLanes) { 14852 // This is always non-null on a ClassComponent or HostRoot 14853 var queue = workInProgress.updateQueue; 14854 hasForceUpdate = false; 14855 14856 { 14857 currentlyProcessingQueue = queue.shared; 14858 } 14859 14860 var firstBaseUpdate = queue.firstBaseUpdate; 14861 var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. 14862 14863 var pendingQueue = queue.shared.pending; 14864 14865 if (pendingQueue !== null) { 14866 queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first 14867 // and last so that it's non-circular. 14868 14869 var lastPendingUpdate = pendingQueue; 14870 var firstPendingUpdate = lastPendingUpdate.next; 14871 lastPendingUpdate.next = null; // Append pending updates to base queue 14872 14873 if (lastBaseUpdate === null) { 14874 firstBaseUpdate = firstPendingUpdate; 14875 } else { 14876 lastBaseUpdate.next = firstPendingUpdate; 14877 } 14878 14879 lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then 14880 // we need to transfer the updates to that queue, too. Because the base 14881 // queue is a singly-linked list with no cycles, we can append to both 14882 // lists and take advantage of structural sharing. 14883 // TODO: Pass `current` as argument 14884 14885 var current = workInProgress.alternate; 14886 14887 if (current !== null) { 14888 // This is always non-null on a ClassComponent or HostRoot 14889 var currentQueue = current.updateQueue; 14890 var currentLastBaseUpdate = currentQueue.lastBaseUpdate; 14891 14892 if (currentLastBaseUpdate !== lastBaseUpdate) { 14893 if (currentLastBaseUpdate === null) { 14894 currentQueue.firstBaseUpdate = firstPendingUpdate; 14895 } else { 14896 currentLastBaseUpdate.next = firstPendingUpdate; 14897 } 14898 14899 currentQueue.lastBaseUpdate = lastPendingUpdate; 14900 } 14901 } 14902 } // These values may change as we process the queue. 14903 14904 14905 if (firstBaseUpdate !== null) { 14906 // Iterate through the list of updates to compute the result. 14907 var newState = queue.baseState; // TODO: Don't need to accumulate this. Instead, we can remove renderLanes 14908 // from the original lanes. 14909 14910 var newLanes = NoLanes; 14911 var newBaseState = null; 14912 var newFirstBaseUpdate = null; 14913 var newLastBaseUpdate = null; 14914 var update = firstBaseUpdate; 14915 14916 do { 14917 var updateLane = update.lane; 14918 var updateEventTime = update.eventTime; 14919 14920 if (!isSubsetOfLanes(renderLanes, updateLane)) { 14921 // Priority is insufficient. Skip this update. If this is the first 14922 // skipped update, the previous update/state is the new base 14923 // update/state. 14924 var clone = { 14925 eventTime: updateEventTime, 14926 lane: updateLane, 14927 tag: update.tag, 14928 payload: update.payload, 14929 callback: update.callback, 14930 next: null 14931 }; 14932 14933 if (newLastBaseUpdate === null) { 14934 newFirstBaseUpdate = newLastBaseUpdate = clone; 14935 newBaseState = newState; 14936 } else { 14937 newLastBaseUpdate = newLastBaseUpdate.next = clone; 14938 } // Update the remaining priority in the queue. 14939 14940 14941 newLanes = mergeLanes(newLanes, updateLane); 14942 } else { 14943 // This update does have sufficient priority. 14944 if (newLastBaseUpdate !== null) { 14945 var _clone = { 14946 eventTime: updateEventTime, 14947 // This update is going to be committed so we never want uncommit 14948 // it. Using NoLane works because 0 is a subset of all bitmasks, so 14949 // this will never be skipped by the check above. 14950 lane: NoLane, 14951 tag: update.tag, 14952 payload: update.payload, 14953 callback: update.callback, 14954 next: null 14955 }; 14956 newLastBaseUpdate = newLastBaseUpdate.next = _clone; 14957 } // Process this update. 14958 14959 14960 newState = getStateFromUpdate(workInProgress, queue, update, newState, props, instance); 14961 var callback = update.callback; 14962 14963 if (callback !== null && // If the update was already committed, we should not queue its 14964 // callback again. 14965 update.lane !== NoLane) { 14966 workInProgress.flags |= Callback; 14967 var effects = queue.effects; 14968 14969 if (effects === null) { 14970 queue.effects = [update]; 14971 } else { 14972 effects.push(update); 14973 } 14974 } 14975 } 14976 14977 update = update.next; 14978 14979 if (update === null) { 14980 pendingQueue = queue.shared.pending; 14981 14982 if (pendingQueue === null) { 14983 break; 14984 } else { 14985 // An update was scheduled from inside a reducer. Add the new 14986 // pending updates to the end of the list and keep processing. 14987 var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we 14988 // unravel them when transferring them to the base queue. 14989 14990 var _firstPendingUpdate = _lastPendingUpdate.next; 14991 _lastPendingUpdate.next = null; 14992 update = _firstPendingUpdate; 14993 queue.lastBaseUpdate = _lastPendingUpdate; 14994 queue.shared.pending = null; 14995 } 14996 } 14997 } while (true); 14998 14999 if (newLastBaseUpdate === null) { 15000 newBaseState = newState; 15001 } 15002 15003 queue.baseState = newBaseState; 15004 queue.firstBaseUpdate = newFirstBaseUpdate; 15005 queue.lastBaseUpdate = newLastBaseUpdate; // Interleaved updates are stored on a separate queue. We aren't going to 15006 // process them during this render, but we do need to track which lanes 15007 // are remaining. 15008 15009 var lastInterleaved = queue.shared.interleaved; 15010 15011 if (lastInterleaved !== null) { 15012 var interleaved = lastInterleaved; 15013 15014 do { 15015 newLanes = mergeLanes(newLanes, interleaved.lane); 15016 interleaved = interleaved.next; 15017 } while (interleaved !== lastInterleaved); 15018 } else if (firstBaseUpdate === null) { 15019 // `queue.lanes` is used for entangling transitions. We can set it back to 15020 // zero once the queue is empty. 15021 queue.shared.lanes = NoLanes; 15022 } // Set the remaining expiration time to be whatever is remaining in the queue. 15023 // This should be fine because the only two other things that contribute to 15024 // expiration time are props and context. We're already in the middle of the 15025 // begin phase by the time we start processing the queue, so we've already 15026 // dealt with the props. Context in components that specify 15027 // shouldComponentUpdate is tricky; but we'll have to account for 15028 // that regardless. 15029 15030 15031 markSkippedUpdateLanes(newLanes); 15032 workInProgress.lanes = newLanes; 15033 workInProgress.memoizedState = newState; 15034 } 15035 15036 { 15037 currentlyProcessingQueue = null; 15038 } 15039 } 15040 15041 function callCallback(callback, context) { 15042 if (typeof callback !== 'function') { 15043 throw new Error('Invalid argument passed as callback. Expected a function. Instead ' + ("received: " + callback)); 15044 } 15045 15046 callback.call(context); 15047 } 15048 15049 function resetHasForceUpdateBeforeProcessing() { 15050 hasForceUpdate = false; 15051 } 15052 function checkHasForceUpdateAfterProcessing() { 15053 return hasForceUpdate; 15054 } 15055 function commitUpdateQueue(finishedWork, finishedQueue, instance) { 15056 // Commit the effects 15057 var effects = finishedQueue.effects; 15058 finishedQueue.effects = null; 15059 15060 if (effects !== null) { 15061 for (var i = 0; i < effects.length; i++) { 15062 var effect = effects[i]; 15063 var callback = effect.callback; 15064 15065 if (callback !== null) { 15066 effect.callback = null; 15067 callCallback(callback, instance); 15068 } 15069 } 15070 } 15071 } 15072 15073 var NO_CONTEXT = {}; 15074 var contextStackCursor$1 = createCursor(NO_CONTEXT); 15075 var contextFiberStackCursor = createCursor(NO_CONTEXT); 15076 var rootInstanceStackCursor = createCursor(NO_CONTEXT); 15077 15078 function requiredContext(c) { 15079 if (c === NO_CONTEXT) { 15080 throw new Error('Expected host context to exist. This error is likely caused by a bug ' + 'in React. Please file an issue.'); 15081 } 15082 15083 return c; 15084 } 15085 15086 function getRootHostContainer() { 15087 var rootInstance = requiredContext(rootInstanceStackCursor.current); 15088 return rootInstance; 15089 } 15090 15091 function pushHostContainer(fiber, nextRootInstance) { 15092 // Push current root instance onto the stack; 15093 // This allows us to reset root when portals are popped. 15094 push(rootInstanceStackCursor, nextRootInstance, fiber); // Track the context and the Fiber that provided it. 15095 // This enables us to pop only Fibers that provide unique contexts. 15096 15097 push(contextFiberStackCursor, fiber, fiber); // Finally, we need to push the host context to the stack. 15098 // However, we can't just call getRootHostContext() and push it because 15099 // we'd have a different number of entries on the stack depending on 15100 // whether getRootHostContext() throws somewhere in renderer code or not. 15101 // So we push an empty value first. This lets us safely unwind on errors. 15102 15103 push(contextStackCursor$1, NO_CONTEXT, fiber); 15104 var nextRootContext = getRootHostContext(nextRootInstance); // Now that we know this function doesn't throw, replace it. 15105 15106 pop(contextStackCursor$1, fiber); 15107 push(contextStackCursor$1, nextRootContext, fiber); 15108 } 15109 15110 function popHostContainer(fiber) { 15111 pop(contextStackCursor$1, fiber); 15112 pop(contextFiberStackCursor, fiber); 15113 pop(rootInstanceStackCursor, fiber); 15114 } 15115 15116 function getHostContext() { 15117 var context = requiredContext(contextStackCursor$1.current); 15118 return context; 15119 } 15120 15121 function pushHostContext(fiber) { 15122 var rootInstance = requiredContext(rootInstanceStackCursor.current); 15123 var context = requiredContext(contextStackCursor$1.current); 15124 var nextContext = getChildHostContext(context, fiber.type); // Don't push this Fiber's context unless it's unique. 15125 15126 if (context === nextContext) { 15127 return; 15128 } // Track the context and the Fiber that provided it. 15129 // This enables us to pop only Fibers that provide unique contexts. 15130 15131 15132 push(contextFiberStackCursor, fiber, fiber); 15133 push(contextStackCursor$1, nextContext, fiber); 15134 } 15135 15136 function popHostContext(fiber) { 15137 // Do not pop unless this Fiber provided the current context. 15138 // pushHostContext() only pushes Fibers that provide unique contexts. 15139 if (contextFiberStackCursor.current !== fiber) { 15140 return; 15141 } 15142 15143 pop(contextStackCursor$1, fiber); 15144 pop(contextFiberStackCursor, fiber); 15145 } 15146 15147 var DefaultSuspenseContext = 0; // The Suspense Context is split into two parts. The lower bits is 15148 // inherited deeply down the subtree. The upper bits only affect 15149 // this immediate suspense boundary and gets reset each new 15150 // boundary or suspense list. 15151 15152 var SubtreeSuspenseContextMask = 1; // Subtree Flags: 15153 // InvisibleParentSuspenseContext indicates that one of our parent Suspense 15154 // boundaries is not currently showing visible main content. 15155 // Either because it is already showing a fallback or is not mounted at all. 15156 // We can use this to determine if it is desirable to trigger a fallback at 15157 // the parent. If not, then we might need to trigger undesirable boundaries 15158 // and/or suspend the commit to avoid hiding the parent content. 15159 15160 var InvisibleParentSuspenseContext = 1; // Shallow Flags: 15161 // ForceSuspenseFallback can be used by SuspenseList to force newly added 15162 // items into their fallback state during one of the render passes. 15163 15164 var ForceSuspenseFallback = 2; 15165 var suspenseStackCursor = createCursor(DefaultSuspenseContext); 15166 function hasSuspenseContext(parentContext, flag) { 15167 return (parentContext & flag) !== 0; 15168 } 15169 function setDefaultShallowSuspenseContext(parentContext) { 15170 return parentContext & SubtreeSuspenseContextMask; 15171 } 15172 function setShallowSuspenseContext(parentContext, shallowContext) { 15173 return parentContext & SubtreeSuspenseContextMask | shallowContext; 15174 } 15175 function addSubtreeSuspenseContext(parentContext, subtreeContext) { 15176 return parentContext | subtreeContext; 15177 } 15178 function pushSuspenseContext(fiber, newContext) { 15179 push(suspenseStackCursor, newContext, fiber); 15180 } 15181 function popSuspenseContext(fiber) { 15182 pop(suspenseStackCursor, fiber); 15183 } 15184 15185 function shouldCaptureSuspense(workInProgress, hasInvisibleParent) { 15186 // If it was the primary children that just suspended, capture and render the 15187 // fallback. Otherwise, don't capture and bubble to the next boundary. 15188 var nextState = workInProgress.memoizedState; 15189 15190 if (nextState !== null) { 15191 if (nextState.dehydrated !== null) { 15192 // A dehydrated boundary always captures. 15193 return true; 15194 } 15195 15196 return false; 15197 } 15198 15199 var props = workInProgress.memoizedProps; // Regular boundaries always capture. 15200 15201 { 15202 return true; 15203 } // If it's a boundary we should avoid, then we prefer to bubble up to the 15204 } 15205 function findFirstSuspended(row) { 15206 var node = row; 15207 15208 while (node !== null) { 15209 if (node.tag === SuspenseComponent) { 15210 var state = node.memoizedState; 15211 15212 if (state !== null) { 15213 var dehydrated = state.dehydrated; 15214 15215 if (dehydrated === null || isSuspenseInstancePending(dehydrated) || isSuspenseInstanceFallback(dehydrated)) { 15216 return node; 15217 } 15218 } 15219 } else if (node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't 15220 // keep track of whether it suspended or not. 15221 node.memoizedProps.revealOrder !== undefined) { 15222 var didSuspend = (node.flags & DidCapture) !== NoFlags; 15223 15224 if (didSuspend) { 15225 return node; 15226 } 15227 } else if (node.child !== null) { 15228 node.child.return = node; 15229 node = node.child; 15230 continue; 15231 } 15232 15233 if (node === row) { 15234 return null; 15235 } 15236 15237 while (node.sibling === null) { 15238 if (node.return === null || node.return === row) { 15239 return null; 15240 } 15241 15242 node = node.return; 15243 } 15244 15245 node.sibling.return = node.return; 15246 node = node.sibling; 15247 } 15248 15249 return null; 15250 } 15251 15252 var NoFlags$1 = 15253 /* */ 15254 0; // Represents whether effect should fire. 15255 15256 var HasEffect = 15257 /* */ 15258 1; // Represents the phase in which the effect (not the clean-up) fires. 15259 15260 var Insertion = 15261 /* */ 15262 2; 15263 var Layout = 15264 /* */ 15265 4; 15266 var Passive$1 = 15267 /* */ 15268 8; 15269 15270 // and should be reset before starting a new render. 15271 // This tracks which mutable sources need to be reset after a render. 15272 15273 var workInProgressSources = []; 15274 function resetWorkInProgressVersions() { 15275 for (var i = 0; i < workInProgressSources.length; i++) { 15276 var mutableSource = workInProgressSources[i]; 15277 15278 { 15279 mutableSource._workInProgressVersionPrimary = null; 15280 } 15281 } 15282 15283 workInProgressSources.length = 0; 15284 } 15285 // This ensures that the version used for server rendering matches the one 15286 // that is eventually read during hydration. 15287 // If they don't match there's a potential tear and a full deopt render is required. 15288 15289 function registerMutableSourceForHydration(root, mutableSource) { 15290 var getVersion = mutableSource._getVersion; 15291 var version = getVersion(mutableSource._source); // TODO Clear this data once all pending hydration work is finished. 15292 // Retaining it forever may interfere with GC. 15293 15294 if (root.mutableSourceEagerHydrationData == null) { 15295 root.mutableSourceEagerHydrationData = [mutableSource, version]; 15296 } else { 15297 root.mutableSourceEagerHydrationData.push(mutableSource, version); 15298 } 15299 } 15300 15301 var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, 15302 ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig; 15303 var didWarnAboutMismatchedHooksForComponent; 15304 var didWarnUncachedGetSnapshot; 15305 15306 { 15307 didWarnAboutMismatchedHooksForComponent = new Set(); 15308 } 15309 15310 // These are set right before calling the component. 15311 var renderLanes = NoLanes; // The work-in-progress fiber. I've named it differently to distinguish it from 15312 // the work-in-progress hook. 15313 15314 var currentlyRenderingFiber$1 = null; // Hooks are stored as a linked list on the fiber's memoizedState field. The 15315 // current hook list is the list that belongs to the current fiber. The 15316 // work-in-progress hook list is a new list that will be added to the 15317 // work-in-progress fiber. 15318 15319 var currentHook = null; 15320 var workInProgressHook = null; // Whether an update was scheduled at any point during the render phase. This 15321 // does not get reset if we do another render pass; only when we're completely 15322 // finished evaluating this component. This is an optimization so we know 15323 // whether we need to clear render phase updates after a throw. 15324 15325 var didScheduleRenderPhaseUpdate = false; // Where an update was scheduled only during the current render pass. This 15326 // gets reset after each attempt. 15327 // TODO: Maybe there's some way to consolidate this with 15328 // `didScheduleRenderPhaseUpdate`. Or with `numberOfReRenders`. 15329 15330 var didScheduleRenderPhaseUpdateDuringThisPass = false; // Counts the number of useId hooks in this component. 15331 15332 var localIdCounter = 0; // Used for ids that are generated completely client-side (i.e. not during 15333 // hydration). This counter is global, so client ids are not stable across 15334 // render attempts. 15335 15336 var globalClientIdCounter = 0; 15337 var RE_RENDER_LIMIT = 25; // In DEV, this is the name of the currently executing primitive hook 15338 15339 var currentHookNameInDev = null; // In DEV, this list ensures that hooks are called in the same order between renders. 15340 // The list stores the order of hooks used during the initial render (mount). 15341 // Subsequent renders (updates) reference this list. 15342 15343 var hookTypesDev = null; 15344 var hookTypesUpdateIndexDev = -1; // In DEV, this tracks whether currently rendering component needs to ignore 15345 // the dependencies for Hooks that need them (e.g. useEffect or useMemo). 15346 // When true, such Hooks will always be "remounted". Only used during hot reload. 15347 15348 var ignorePreviousDependencies = false; 15349 15350 function mountHookTypesDev() { 15351 { 15352 var hookName = currentHookNameInDev; 15353 15354 if (hookTypesDev === null) { 15355 hookTypesDev = [hookName]; 15356 } else { 15357 hookTypesDev.push(hookName); 15358 } 15359 } 15360 } 15361 15362 function updateHookTypesDev() { 15363 { 15364 var hookName = currentHookNameInDev; 15365 15366 if (hookTypesDev !== null) { 15367 hookTypesUpdateIndexDev++; 15368 15369 if (hookTypesDev[hookTypesUpdateIndexDev] !== hookName) { 15370 warnOnHookMismatchInDev(hookName); 15371 } 15372 } 15373 } 15374 } 15375 15376 function checkDepsAreArrayDev(deps) { 15377 { 15378 if (deps !== undefined && deps !== null && !isArray(deps)) { 15379 // Verify deps, but only on mount to avoid extra checks. 15380 // It's unlikely their type would change as usually you define them inline. 15381 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); 15382 } 15383 } 15384 } 15385 15386 function warnOnHookMismatchInDev(currentHookName) { 15387 { 15388 var componentName = getComponentNameFromFiber(currentlyRenderingFiber$1); 15389 15390 if (!didWarnAboutMismatchedHooksForComponent.has(componentName)) { 15391 didWarnAboutMismatchedHooksForComponent.add(componentName); 15392 15393 if (hookTypesDev !== null) { 15394 var table = ''; 15395 var secondColumnStart = 30; 15396 15397 for (var i = 0; i <= hookTypesUpdateIndexDev; i++) { 15398 var oldHookName = hookTypesDev[i]; 15399 var newHookName = i === hookTypesUpdateIndexDev ? currentHookName : oldHookName; 15400 var row = i + 1 + ". " + oldHookName; // Extra space so second column lines up 15401 // lol @ IE not supporting String#repeat 15402 15403 while (row.length < secondColumnStart) { 15404 row += ' '; 15405 } 15406 15407 row += newHookName + '\n'; 15408 table += row; 15409 } 15410 15411 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); 15412 } 15413 } 15414 } 15415 } 15416 15417 function throwInvalidHookError() { 15418 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.'); 15419 } 15420 15421 function areHookInputsEqual(nextDeps, prevDeps) { 15422 { 15423 if (ignorePreviousDependencies) { 15424 // Only true when this component is being hot reloaded. 15425 return false; 15426 } 15427 } 15428 15429 if (prevDeps === null) { 15430 { 15431 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); 15432 } 15433 15434 return false; 15435 } 15436 15437 { 15438 // Don't bother comparing lengths in prod because these arrays should be 15439 // passed inline. 15440 if (nextDeps.length !== prevDeps.length) { 15441 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(', ') + "]"); 15442 } 15443 } 15444 15445 for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) { 15446 if (objectIs(nextDeps[i], prevDeps[i])) { 15447 continue; 15448 } 15449 15450 return false; 15451 } 15452 15453 return true; 15454 } 15455 15456 function renderWithHooks(current, workInProgress, Component, props, secondArg, nextRenderLanes) { 15457 renderLanes = nextRenderLanes; 15458 currentlyRenderingFiber$1 = workInProgress; 15459 15460 { 15461 hookTypesDev = current !== null ? current._debugHookTypes : null; 15462 hookTypesUpdateIndexDev = -1; // Used for hot reloading: 15463 15464 ignorePreviousDependencies = current !== null && current.type !== workInProgress.type; 15465 } 15466 15467 workInProgress.memoizedState = null; 15468 workInProgress.updateQueue = null; 15469 workInProgress.lanes = NoLanes; // The following should have already been reset 15470 // currentHook = null; 15471 // workInProgressHook = null; 15472 // didScheduleRenderPhaseUpdate = false; 15473 // localIdCounter = 0; 15474 // TODO Warn if no hooks are used at all during mount, then some are used during update. 15475 // Currently we will identify the update render as a mount because memoizedState === null. 15476 // This is tricky because it's valid for certain types of components (e.g. React.lazy) 15477 // Using memoizedState to differentiate between mount/update only works if at least one stateful hook is used. 15478 // Non-stateful hooks (e.g. context) don't get added to memoizedState, 15479 // so memoizedState would be null during updates and mounts. 15480 15481 { 15482 if (current !== null && current.memoizedState !== null) { 15483 ReactCurrentDispatcher$1.current = HooksDispatcherOnUpdateInDEV; 15484 } else if (hookTypesDev !== null) { 15485 // This dispatcher handles an edge case where a component is updating, 15486 // but no stateful hooks have been used. 15487 // We want to match the production code behavior (which will use HooksDispatcherOnMount), 15488 // but with the extra DEV validation to ensure hooks ordering hasn't changed. 15489 // This dispatcher does that. 15490 ReactCurrentDispatcher$1.current = HooksDispatcherOnMountWithHookTypesInDEV; 15491 } else { 15492 ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; 15493 } 15494 } 15495 15496 var children = Component(props, secondArg); // Check if there was a render phase update 15497 15498 if (didScheduleRenderPhaseUpdateDuringThisPass) { 15499 // Keep rendering in a loop for as long as render phase updates continue to 15500 // be scheduled. Use a counter to prevent infinite loops. 15501 var numberOfReRenders = 0; 15502 15503 do { 15504 didScheduleRenderPhaseUpdateDuringThisPass = false; 15505 localIdCounter = 0; 15506 15507 if (numberOfReRenders >= RE_RENDER_LIMIT) { 15508 throw new Error('Too many re-renders. React limits the number of renders to prevent ' + 'an infinite loop.'); 15509 } 15510 15511 numberOfReRenders += 1; 15512 15513 { 15514 // Even when hot reloading, allow dependencies to stabilize 15515 // after first render to prevent infinite render phase updates. 15516 ignorePreviousDependencies = false; 15517 } // Start over from the beginning of the list 15518 15519 15520 currentHook = null; 15521 workInProgressHook = null; 15522 workInProgress.updateQueue = null; 15523 15524 { 15525 // Also validate hook order for cascading updates. 15526 hookTypesUpdateIndexDev = -1; 15527 } 15528 15529 ReactCurrentDispatcher$1.current = HooksDispatcherOnRerenderInDEV ; 15530 children = Component(props, secondArg); 15531 } while (didScheduleRenderPhaseUpdateDuringThisPass); 15532 } // We can assume the previous dispatcher is always this one, since we set it 15533 // at the beginning of the render phase and there's no re-entrance. 15534 15535 15536 ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; 15537 15538 { 15539 workInProgress._debugHookTypes = hookTypesDev; 15540 } // This check uses currentHook so that it works the same in DEV and prod bundles. 15541 // hookTypesDev could catch more cases (e.g. context) but only in DEV bundles. 15542 15543 15544 var didRenderTooFewHooks = currentHook !== null && currentHook.next !== null; 15545 renderLanes = NoLanes; 15546 currentlyRenderingFiber$1 = null; 15547 currentHook = null; 15548 workInProgressHook = null; 15549 15550 { 15551 currentHookNameInDev = null; 15552 hookTypesDev = null; 15553 hookTypesUpdateIndexDev = -1; // Confirm that a static flag was not added or removed since the last 15554 // render. If this fires, it suggests that we incorrectly reset the static 15555 // flags in some other part of the codebase. This has happened before, for 15556 // example, in the SuspenseList implementation. 15557 15558 if (current !== null && (current.flags & StaticMask) !== (workInProgress.flags & StaticMask) && // Disable this warning in legacy mode, because legacy Suspense is weird 15559 // and creates false positives. To make this work in legacy mode, we'd 15560 // need to mark fibers that commit in an incomplete state, somehow. For 15561 // now I'll disable the warning that most of the bugs that would trigger 15562 // it are either exclusive to concurrent mode or exist in both. 15563 (current.mode & ConcurrentMode) !== NoMode) { 15564 error('Internal React error: Expected static flag was missing. Please ' + 'notify the React team.'); 15565 } 15566 } 15567 15568 didScheduleRenderPhaseUpdate = false; // This is reset by checkDidRenderIdHook 15569 // localIdCounter = 0; 15570 15571 if (didRenderTooFewHooks) { 15572 throw new Error('Rendered fewer hooks than expected. This may be caused by an accidental ' + 'early return statement.'); 15573 } 15574 15575 return children; 15576 } 15577 function checkDidRenderIdHook() { 15578 // This should be called immediately after every renderWithHooks call. 15579 // Conceptually, it's part of the return value of renderWithHooks; it's only a 15580 // separate function to avoid using an array tuple. 15581 var didRenderIdHook = localIdCounter !== 0; 15582 localIdCounter = 0; 15583 return didRenderIdHook; 15584 } 15585 function bailoutHooks(current, workInProgress, lanes) { 15586 workInProgress.updateQueue = current.updateQueue; // TODO: Don't need to reset the flags here, because they're reset in the 15587 // complete phase (bubbleProperties). 15588 15589 if ( (workInProgress.mode & StrictEffectsMode) !== NoMode) { 15590 workInProgress.flags &= ~(MountPassiveDev | MountLayoutDev | Passive | Update); 15591 } else { 15592 workInProgress.flags &= ~(Passive | Update); 15593 } 15594 15595 current.lanes = removeLanes(current.lanes, lanes); 15596 } 15597 function resetHooksAfterThrow() { 15598 // We can assume the previous dispatcher is always this one, since we set it 15599 // at the beginning of the render phase and there's no re-entrance. 15600 ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; 15601 15602 if (didScheduleRenderPhaseUpdate) { 15603 // There were render phase updates. These are only valid for this render 15604 // phase, which we are now aborting. Remove the updates from the queues so 15605 // they do not persist to the next render. Do not remove updates from hooks 15606 // that weren't processed. 15607 // 15608 // Only reset the updates from the queue if it has a clone. If it does 15609 // not have a clone, that means it wasn't processed, and the updates were 15610 // scheduled before we entered the render phase. 15611 var hook = currentlyRenderingFiber$1.memoizedState; 15612 15613 while (hook !== null) { 15614 var queue = hook.queue; 15615 15616 if (queue !== null) { 15617 queue.pending = null; 15618 } 15619 15620 hook = hook.next; 15621 } 15622 15623 didScheduleRenderPhaseUpdate = false; 15624 } 15625 15626 renderLanes = NoLanes; 15627 currentlyRenderingFiber$1 = null; 15628 currentHook = null; 15629 workInProgressHook = null; 15630 15631 { 15632 hookTypesDev = null; 15633 hookTypesUpdateIndexDev = -1; 15634 currentHookNameInDev = null; 15635 isUpdatingOpaqueValueInRenderPhase = false; 15636 } 15637 15638 didScheduleRenderPhaseUpdateDuringThisPass = false; 15639 localIdCounter = 0; 15640 } 15641 15642 function mountWorkInProgressHook() { 15643 var hook = { 15644 memoizedState: null, 15645 baseState: null, 15646 baseQueue: null, 15647 queue: null, 15648 next: null 15649 }; 15650 15651 if (workInProgressHook === null) { 15652 // This is the first hook in the list 15653 currentlyRenderingFiber$1.memoizedState = workInProgressHook = hook; 15654 } else { 15655 // Append to the end of the list 15656 workInProgressHook = workInProgressHook.next = hook; 15657 } 15658 15659 return workInProgressHook; 15660 } 15661 15662 function updateWorkInProgressHook() { 15663 // This function is used both for updates and for re-renders triggered by a 15664 // render phase update. It assumes there is either a current hook we can 15665 // clone, or a work-in-progress hook from a previous render pass that we can 15666 // use as a base. When we reach the end of the base list, we must switch to 15667 // the dispatcher used for mounts. 15668 var nextCurrentHook; 15669 15670 if (currentHook === null) { 15671 var current = currentlyRenderingFiber$1.alternate; 15672 15673 if (current !== null) { 15674 nextCurrentHook = current.memoizedState; 15675 } else { 15676 nextCurrentHook = null; 15677 } 15678 } else { 15679 nextCurrentHook = currentHook.next; 15680 } 15681 15682 var nextWorkInProgressHook; 15683 15684 if (workInProgressHook === null) { 15685 nextWorkInProgressHook = currentlyRenderingFiber$1.memoizedState; 15686 } else { 15687 nextWorkInProgressHook = workInProgressHook.next; 15688 } 15689 15690 if (nextWorkInProgressHook !== null) { 15691 // There's already a work-in-progress. Reuse it. 15692 workInProgressHook = nextWorkInProgressHook; 15693 nextWorkInProgressHook = workInProgressHook.next; 15694 currentHook = nextCurrentHook; 15695 } else { 15696 // Clone from the current hook. 15697 if (nextCurrentHook === null) { 15698 throw new Error('Rendered more hooks than during the previous render.'); 15699 } 15700 15701 currentHook = nextCurrentHook; 15702 var newHook = { 15703 memoizedState: currentHook.memoizedState, 15704 baseState: currentHook.baseState, 15705 baseQueue: currentHook.baseQueue, 15706 queue: currentHook.queue, 15707 next: null 15708 }; 15709 15710 if (workInProgressHook === null) { 15711 // This is the first hook in the list. 15712 currentlyRenderingFiber$1.memoizedState = workInProgressHook = newHook; 15713 } else { 15714 // Append to the end of the list. 15715 workInProgressHook = workInProgressHook.next = newHook; 15716 } 15717 } 15718 15719 return workInProgressHook; 15720 } 15721 15722 function createFunctionComponentUpdateQueue() { 15723 return { 15724 lastEffect: null, 15725 stores: null 15726 }; 15727 } 15728 15729 function basicStateReducer(state, action) { 15730 // $FlowFixMe: Flow doesn't like mixed types 15731 return typeof action === 'function' ? action(state) : action; 15732 } 15733 15734 function mountReducer(reducer, initialArg, init) { 15735 var hook = mountWorkInProgressHook(); 15736 var initialState; 15737 15738 if (init !== undefined) { 15739 initialState = init(initialArg); 15740 } else { 15741 initialState = initialArg; 15742 } 15743 15744 hook.memoizedState = hook.baseState = initialState; 15745 var queue = { 15746 pending: null, 15747 interleaved: null, 15748 lanes: NoLanes, 15749 dispatch: null, 15750 lastRenderedReducer: reducer, 15751 lastRenderedState: initialState 15752 }; 15753 hook.queue = queue; 15754 var dispatch = queue.dispatch = dispatchReducerAction.bind(null, currentlyRenderingFiber$1, queue); 15755 return [hook.memoizedState, dispatch]; 15756 } 15757 15758 function updateReducer(reducer, initialArg, init) { 15759 var hook = updateWorkInProgressHook(); 15760 var queue = hook.queue; 15761 15762 if (queue === null) { 15763 throw new Error('Should have a queue. This is likely a bug in React. Please file an issue.'); 15764 } 15765 15766 queue.lastRenderedReducer = reducer; 15767 var current = currentHook; // The last rebase update that is NOT part of the base state. 15768 15769 var baseQueue = current.baseQueue; // The last pending update that hasn't been processed yet. 15770 15771 var pendingQueue = queue.pending; 15772 15773 if (pendingQueue !== null) { 15774 // We have new updates that haven't been processed yet. 15775 // We'll add them to the base queue. 15776 if (baseQueue !== null) { 15777 // Merge the pending queue and the base queue. 15778 var baseFirst = baseQueue.next; 15779 var pendingFirst = pendingQueue.next; 15780 baseQueue.next = pendingFirst; 15781 pendingQueue.next = baseFirst; 15782 } 15783 15784 { 15785 if (current.baseQueue !== baseQueue) { 15786 // Internal invariant that should never happen, but feasibly could in 15787 // the future if we implement resuming, or some form of that. 15788 error('Internal error: Expected work-in-progress queue to be a clone. ' + 'This is a bug in React.'); 15789 } 15790 } 15791 15792 current.baseQueue = baseQueue = pendingQueue; 15793 queue.pending = null; 15794 } 15795 15796 if (baseQueue !== null) { 15797 // We have a queue to process. 15798 var first = baseQueue.next; 15799 var newState = current.baseState; 15800 var newBaseState = null; 15801 var newBaseQueueFirst = null; 15802 var newBaseQueueLast = null; 15803 var update = first; 15804 15805 do { 15806 var updateLane = update.lane; 15807 15808 if (!isSubsetOfLanes(renderLanes, updateLane)) { 15809 // Priority is insufficient. Skip this update. If this is the first 15810 // skipped update, the previous update/state is the new base 15811 // update/state. 15812 var clone = { 15813 lane: updateLane, 15814 action: update.action, 15815 hasEagerState: update.hasEagerState, 15816 eagerState: update.eagerState, 15817 next: null 15818 }; 15819 15820 if (newBaseQueueLast === null) { 15821 newBaseQueueFirst = newBaseQueueLast = clone; 15822 newBaseState = newState; 15823 } else { 15824 newBaseQueueLast = newBaseQueueLast.next = clone; 15825 } // Update the remaining priority in the queue. 15826 // TODO: Don't need to accumulate this. Instead, we can remove 15827 // renderLanes from the original lanes. 15828 15829 15830 currentlyRenderingFiber$1.lanes = mergeLanes(currentlyRenderingFiber$1.lanes, updateLane); 15831 markSkippedUpdateLanes(updateLane); 15832 } else { 15833 // This update does have sufficient priority. 15834 if (newBaseQueueLast !== null) { 15835 var _clone = { 15836 // This update is going to be committed so we never want uncommit 15837 // it. Using NoLane works because 0 is a subset of all bitmasks, so 15838 // this will never be skipped by the check above. 15839 lane: NoLane, 15840 action: update.action, 15841 hasEagerState: update.hasEagerState, 15842 eagerState: update.eagerState, 15843 next: null 15844 }; 15845 newBaseQueueLast = newBaseQueueLast.next = _clone; 15846 } // Process this update. 15847 15848 15849 if (update.hasEagerState) { 15850 // If this update is a state update (not a reducer) and was processed eagerly, 15851 // we can use the eagerly computed state 15852 newState = update.eagerState; 15853 } else { 15854 var action = update.action; 15855 newState = reducer(newState, action); 15856 } 15857 } 15858 15859 update = update.next; 15860 } while (update !== null && update !== first); 15861 15862 if (newBaseQueueLast === null) { 15863 newBaseState = newState; 15864 } else { 15865 newBaseQueueLast.next = newBaseQueueFirst; 15866 } // Mark that the fiber performed work, but only if the new state is 15867 // different from the current state. 15868 15869 15870 if (!objectIs(newState, hook.memoizedState)) { 15871 markWorkInProgressReceivedUpdate(); 15872 } 15873 15874 hook.memoizedState = newState; 15875 hook.baseState = newBaseState; 15876 hook.baseQueue = newBaseQueueLast; 15877 queue.lastRenderedState = newState; 15878 } // Interleaved updates are stored on a separate queue. We aren't going to 15879 // process them during this render, but we do need to track which lanes 15880 // are remaining. 15881 15882 15883 var lastInterleaved = queue.interleaved; 15884 15885 if (lastInterleaved !== null) { 15886 var interleaved = lastInterleaved; 15887 15888 do { 15889 var interleavedLane = interleaved.lane; 15890 currentlyRenderingFiber$1.lanes = mergeLanes(currentlyRenderingFiber$1.lanes, interleavedLane); 15891 markSkippedUpdateLanes(interleavedLane); 15892 interleaved = interleaved.next; 15893 } while (interleaved !== lastInterleaved); 15894 } else if (baseQueue === null) { 15895 // `queue.lanes` is used for entangling transitions. We can set it back to 15896 // zero once the queue is empty. 15897 queue.lanes = NoLanes; 15898 } 15899 15900 var dispatch = queue.dispatch; 15901 return [hook.memoizedState, dispatch]; 15902 } 15903 15904 function rerenderReducer(reducer, initialArg, init) { 15905 var hook = updateWorkInProgressHook(); 15906 var queue = hook.queue; 15907 15908 if (queue === null) { 15909 throw new Error('Should have a queue. This is likely a bug in React. Please file an issue.'); 15910 } 15911 15912 queue.lastRenderedReducer = reducer; // This is a re-render. Apply the new render phase updates to the previous 15913 // work-in-progress hook. 15914 15915 var dispatch = queue.dispatch; 15916 var lastRenderPhaseUpdate = queue.pending; 15917 var newState = hook.memoizedState; 15918 15919 if (lastRenderPhaseUpdate !== null) { 15920 // The queue doesn't persist past this render pass. 15921 queue.pending = null; 15922 var firstRenderPhaseUpdate = lastRenderPhaseUpdate.next; 15923 var update = firstRenderPhaseUpdate; 15924 15925 do { 15926 // Process this render phase update. We don't have to check the 15927 // priority because it will always be the same as the current 15928 // render's. 15929 var action = update.action; 15930 newState = reducer(newState, action); 15931 update = update.next; 15932 } while (update !== firstRenderPhaseUpdate); // Mark that the fiber performed work, but only if the new state is 15933 // different from the current state. 15934 15935 15936 if (!objectIs(newState, hook.memoizedState)) { 15937 markWorkInProgressReceivedUpdate(); 15938 } 15939 15940 hook.memoizedState = newState; // Don't persist the state accumulated from the render phase updates to 15941 // the base state unless the queue is empty. 15942 // TODO: Not sure if this is the desired semantics, but it's what we 15943 // do for gDSFP. I can't remember why. 15944 15945 if (hook.baseQueue === null) { 15946 hook.baseState = newState; 15947 } 15948 15949 queue.lastRenderedState = newState; 15950 } 15951 15952 return [newState, dispatch]; 15953 } 15954 15955 function mountMutableSource(source, getSnapshot, subscribe) { 15956 { 15957 return undefined; 15958 } 15959 } 15960 15961 function updateMutableSource(source, getSnapshot, subscribe) { 15962 { 15963 return undefined; 15964 } 15965 } 15966 15967 function mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { 15968 var fiber = currentlyRenderingFiber$1; 15969 var hook = mountWorkInProgressHook(); 15970 var nextSnapshot; 15971 var isHydrating = getIsHydrating(); 15972 15973 if (isHydrating) { 15974 if (getServerSnapshot === undefined) { 15975 throw new Error('Missing getServerSnapshot, which is required for ' + 'server-rendered content. Will revert to client rendering.'); 15976 } 15977 15978 nextSnapshot = getServerSnapshot(); 15979 15980 { 15981 if (!didWarnUncachedGetSnapshot) { 15982 if (nextSnapshot !== getServerSnapshot()) { 15983 error('The result of getServerSnapshot should be cached to avoid an infinite loop'); 15984 15985 didWarnUncachedGetSnapshot = true; 15986 } 15987 } 15988 } 15989 } else { 15990 nextSnapshot = getSnapshot(); 15991 15992 { 15993 if (!didWarnUncachedGetSnapshot) { 15994 var cachedSnapshot = getSnapshot(); 15995 15996 if (!objectIs(nextSnapshot, cachedSnapshot)) { 15997 error('The result of getSnapshot should be cached to avoid an infinite loop'); 15998 15999 didWarnUncachedGetSnapshot = true; 16000 } 16001 } 16002 } // Unless we're rendering a blocking lane, schedule a consistency check. 16003 // Right before committing, we will walk the tree and check if any of the 16004 // stores were mutated. 16005 // 16006 // We won't do this if we're hydrating server-rendered content, because if 16007 // the content is stale, it's already visible anyway. Instead we'll patch 16008 // it up in a passive effect. 16009 16010 16011 var root = getWorkInProgressRoot(); 16012 16013 if (root === null) { 16014 throw new Error('Expected a work-in-progress root. This is a bug in React. Please file an issue.'); 16015 } 16016 16017 if (!includesBlockingLane(root, renderLanes)) { 16018 pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); 16019 } 16020 } // Read the current snapshot from the store on every render. This breaks the 16021 // normal rules of React, and only works because store updates are 16022 // always synchronous. 16023 16024 16025 hook.memoizedState = nextSnapshot; 16026 var inst = { 16027 value: nextSnapshot, 16028 getSnapshot: getSnapshot 16029 }; 16030 hook.queue = inst; // Schedule an effect to subscribe to the store. 16031 16032 mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]); // Schedule an effect to update the mutable instance fields. We will update 16033 // this whenever subscribe, getSnapshot, or value changes. Because there's no 16034 // clean-up function, and we track the deps correctly, we can call pushEffect 16035 // directly, without storing any additional state. For the same reason, we 16036 // don't need to set a static flag, either. 16037 // TODO: We can move this to the passive phase once we add a pre-commit 16038 // consistency check. See the next comment. 16039 16040 fiber.flags |= Passive; 16041 pushEffect(HasEffect | Passive$1, updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), undefined, null); 16042 return nextSnapshot; 16043 } 16044 16045 function updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { 16046 var fiber = currentlyRenderingFiber$1; 16047 var hook = updateWorkInProgressHook(); // Read the current snapshot from the store on every render. This breaks the 16048 // normal rules of React, and only works because store updates are 16049 // always synchronous. 16050 16051 var nextSnapshot = getSnapshot(); 16052 16053 { 16054 if (!didWarnUncachedGetSnapshot) { 16055 var cachedSnapshot = getSnapshot(); 16056 16057 if (!objectIs(nextSnapshot, cachedSnapshot)) { 16058 error('The result of getSnapshot should be cached to avoid an infinite loop'); 16059 16060 didWarnUncachedGetSnapshot = true; 16061 } 16062 } 16063 } 16064 16065 var prevSnapshot = hook.memoizedState; 16066 var snapshotChanged = !objectIs(prevSnapshot, nextSnapshot); 16067 16068 if (snapshotChanged) { 16069 hook.memoizedState = nextSnapshot; 16070 markWorkInProgressReceivedUpdate(); 16071 } 16072 16073 var inst = hook.queue; 16074 updateEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]); // Whenever getSnapshot or subscribe changes, we need to check in the 16075 // commit phase if there was an interleaved mutation. In concurrent mode 16076 // this can happen all the time, but even in synchronous mode, an earlier 16077 // effect may have mutated the store. 16078 16079 if (inst.getSnapshot !== getSnapshot || snapshotChanged || // Check if the susbcribe function changed. We can save some memory by 16080 // checking whether we scheduled a subscription effect above. 16081 workInProgressHook !== null && workInProgressHook.memoizedState.tag & HasEffect) { 16082 fiber.flags |= Passive; 16083 pushEffect(HasEffect | Passive$1, updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), undefined, null); // Unless we're rendering a blocking lane, schedule a consistency check. 16084 // Right before committing, we will walk the tree and check if any of the 16085 // stores were mutated. 16086 16087 var root = getWorkInProgressRoot(); 16088 16089 if (root === null) { 16090 throw new Error('Expected a work-in-progress root. This is a bug in React. Please file an issue.'); 16091 } 16092 16093 if (!includesBlockingLane(root, renderLanes)) { 16094 pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); 16095 } 16096 } 16097 16098 return nextSnapshot; 16099 } 16100 16101 function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) { 16102 fiber.flags |= StoreConsistency; 16103 var check = { 16104 getSnapshot: getSnapshot, 16105 value: renderedSnapshot 16106 }; 16107 var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; 16108 16109 if (componentUpdateQueue === null) { 16110 componentUpdateQueue = createFunctionComponentUpdateQueue(); 16111 currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; 16112 componentUpdateQueue.stores = [check]; 16113 } else { 16114 var stores = componentUpdateQueue.stores; 16115 16116 if (stores === null) { 16117 componentUpdateQueue.stores = [check]; 16118 } else { 16119 stores.push(check); 16120 } 16121 } 16122 } 16123 16124 function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) { 16125 // These are updated in the passive phase 16126 inst.value = nextSnapshot; 16127 inst.getSnapshot = getSnapshot; // Something may have been mutated in between render and commit. This could 16128 // have been in an event that fired before the passive effects, or it could 16129 // have been in a layout effect. In that case, we would have used the old 16130 // snapsho and getSnapshot values to bail out. We need to check one more time. 16131 16132 if (checkIfSnapshotChanged(inst)) { 16133 // Force a re-render. 16134 forceStoreRerender(fiber); 16135 } 16136 } 16137 16138 function subscribeToStore(fiber, inst, subscribe) { 16139 var handleStoreChange = function () { 16140 // The store changed. Check if the snapshot changed since the last time we 16141 // read from the store. 16142 if (checkIfSnapshotChanged(inst)) { 16143 // Force a re-render. 16144 forceStoreRerender(fiber); 16145 } 16146 }; // Subscribe to the store and return a clean-up function. 16147 16148 16149 return subscribe(handleStoreChange); 16150 } 16151 16152 function checkIfSnapshotChanged(inst) { 16153 var latestGetSnapshot = inst.getSnapshot; 16154 var prevValue = inst.value; 16155 16156 try { 16157 var nextValue = latestGetSnapshot(); 16158 return !objectIs(prevValue, nextValue); 16159 } catch (error) { 16160 return true; 16161 } 16162 } 16163 16164 function forceStoreRerender(fiber) { 16165 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 16166 16167 if (root !== null) { 16168 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 16169 } 16170 } 16171 16172 function mountState(initialState) { 16173 var hook = mountWorkInProgressHook(); 16174 16175 if (typeof initialState === 'function') { 16176 // $FlowFixMe: Flow doesn't like mixed types 16177 initialState = initialState(); 16178 } 16179 16180 hook.memoizedState = hook.baseState = initialState; 16181 var queue = { 16182 pending: null, 16183 interleaved: null, 16184 lanes: NoLanes, 16185 dispatch: null, 16186 lastRenderedReducer: basicStateReducer, 16187 lastRenderedState: initialState 16188 }; 16189 hook.queue = queue; 16190 var dispatch = queue.dispatch = dispatchSetState.bind(null, currentlyRenderingFiber$1, queue); 16191 return [hook.memoizedState, dispatch]; 16192 } 16193 16194 function updateState(initialState) { 16195 return updateReducer(basicStateReducer); 16196 } 16197 16198 function rerenderState(initialState) { 16199 return rerenderReducer(basicStateReducer); 16200 } 16201 16202 function pushEffect(tag, create, destroy, deps) { 16203 var effect = { 16204 tag: tag, 16205 create: create, 16206 destroy: destroy, 16207 deps: deps, 16208 // Circular 16209 next: null 16210 }; 16211 var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; 16212 16213 if (componentUpdateQueue === null) { 16214 componentUpdateQueue = createFunctionComponentUpdateQueue(); 16215 currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; 16216 componentUpdateQueue.lastEffect = effect.next = effect; 16217 } else { 16218 var lastEffect = componentUpdateQueue.lastEffect; 16219 16220 if (lastEffect === null) { 16221 componentUpdateQueue.lastEffect = effect.next = effect; 16222 } else { 16223 var firstEffect = lastEffect.next; 16224 lastEffect.next = effect; 16225 effect.next = firstEffect; 16226 componentUpdateQueue.lastEffect = effect; 16227 } 16228 } 16229 16230 return effect; 16231 } 16232 16233 function mountRef(initialValue) { 16234 var hook = mountWorkInProgressHook(); 16235 16236 { 16237 var _ref2 = { 16238 current: initialValue 16239 }; 16240 hook.memoizedState = _ref2; 16241 return _ref2; 16242 } 16243 } 16244 16245 function updateRef(initialValue) { 16246 var hook = updateWorkInProgressHook(); 16247 return hook.memoizedState; 16248 } 16249 16250 function mountEffectImpl(fiberFlags, hookFlags, create, deps) { 16251 var hook = mountWorkInProgressHook(); 16252 var nextDeps = deps === undefined ? null : deps; 16253 currentlyRenderingFiber$1.flags |= fiberFlags; 16254 hook.memoizedState = pushEffect(HasEffect | hookFlags, create, undefined, nextDeps); 16255 } 16256 16257 function updateEffectImpl(fiberFlags, hookFlags, create, deps) { 16258 var hook = updateWorkInProgressHook(); 16259 var nextDeps = deps === undefined ? null : deps; 16260 var destroy = undefined; 16261 16262 if (currentHook !== null) { 16263 var prevEffect = currentHook.memoizedState; 16264 destroy = prevEffect.destroy; 16265 16266 if (nextDeps !== null) { 16267 var prevDeps = prevEffect.deps; 16268 16269 if (areHookInputsEqual(nextDeps, prevDeps)) { 16270 hook.memoizedState = pushEffect(hookFlags, create, destroy, nextDeps); 16271 return; 16272 } 16273 } 16274 } 16275 16276 currentlyRenderingFiber$1.flags |= fiberFlags; 16277 hook.memoizedState = pushEffect(HasEffect | hookFlags, create, destroy, nextDeps); 16278 } 16279 16280 function mountEffect(create, deps) { 16281 if ( (currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { 16282 return mountEffectImpl(MountPassiveDev | Passive | PassiveStatic, Passive$1, create, deps); 16283 } else { 16284 return mountEffectImpl(Passive | PassiveStatic, Passive$1, create, deps); 16285 } 16286 } 16287 16288 function updateEffect(create, deps) { 16289 return updateEffectImpl(Passive, Passive$1, create, deps); 16290 } 16291 16292 function mountInsertionEffect(create, deps) { 16293 return mountEffectImpl(Update, Insertion, create, deps); 16294 } 16295 16296 function updateInsertionEffect(create, deps) { 16297 return updateEffectImpl(Update, Insertion, create, deps); 16298 } 16299 16300 function mountLayoutEffect(create, deps) { 16301 var fiberFlags = Update; 16302 16303 { 16304 fiberFlags |= LayoutStatic; 16305 } 16306 16307 if ( (currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { 16308 fiberFlags |= MountLayoutDev; 16309 } 16310 16311 return mountEffectImpl(fiberFlags, Layout, create, deps); 16312 } 16313 16314 function updateLayoutEffect(create, deps) { 16315 return updateEffectImpl(Update, Layout, create, deps); 16316 } 16317 16318 function imperativeHandleEffect(create, ref) { 16319 if (typeof ref === 'function') { 16320 var refCallback = ref; 16321 16322 var _inst = create(); 16323 16324 refCallback(_inst); 16325 return function () { 16326 refCallback(null); 16327 }; 16328 } else if (ref !== null && ref !== undefined) { 16329 var refObject = ref; 16330 16331 { 16332 if (!refObject.hasOwnProperty('current')) { 16333 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(', ') + '}'); 16334 } 16335 } 16336 16337 var _inst2 = create(); 16338 16339 refObject.current = _inst2; 16340 return function () { 16341 refObject.current = null; 16342 }; 16343 } 16344 } 16345 16346 function mountImperativeHandle(ref, create, deps) { 16347 { 16348 if (typeof create !== 'function') { 16349 error('Expected useImperativeHandle() second argument to be a function ' + 'that creates a handle. Instead received: %s.', create !== null ? typeof create : 'null'); 16350 } 16351 } // TODO: If deps are provided, should we skip comparing the ref itself? 16352 16353 16354 var effectDeps = deps !== null && deps !== undefined ? deps.concat([ref]) : null; 16355 var fiberFlags = Update; 16356 16357 { 16358 fiberFlags |= LayoutStatic; 16359 } 16360 16361 if ( (currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { 16362 fiberFlags |= MountLayoutDev; 16363 } 16364 16365 return mountEffectImpl(fiberFlags, Layout, imperativeHandleEffect.bind(null, create, ref), effectDeps); 16366 } 16367 16368 function updateImperativeHandle(ref, create, deps) { 16369 { 16370 if (typeof create !== 'function') { 16371 error('Expected useImperativeHandle() second argument to be a function ' + 'that creates a handle. Instead received: %s.', create !== null ? typeof create : 'null'); 16372 } 16373 } // TODO: If deps are provided, should we skip comparing the ref itself? 16374 16375 16376 var effectDeps = deps !== null && deps !== undefined ? deps.concat([ref]) : null; 16377 return updateEffectImpl(Update, Layout, imperativeHandleEffect.bind(null, create, ref), effectDeps); 16378 } 16379 16380 function mountDebugValue(value, formatterFn) {// This hook is normally a no-op. 16381 // The react-debug-hooks package injects its own implementation 16382 // so that e.g. DevTools can display custom hook values. 16383 } 16384 16385 var updateDebugValue = mountDebugValue; 16386 16387 function mountCallback(callback, deps) { 16388 var hook = mountWorkInProgressHook(); 16389 var nextDeps = deps === undefined ? null : deps; 16390 hook.memoizedState = [callback, nextDeps]; 16391 return callback; 16392 } 16393 16394 function updateCallback(callback, deps) { 16395 var hook = updateWorkInProgressHook(); 16396 var nextDeps = deps === undefined ? null : deps; 16397 var prevState = hook.memoizedState; 16398 16399 if (prevState !== null) { 16400 if (nextDeps !== null) { 16401 var prevDeps = prevState[1]; 16402 16403 if (areHookInputsEqual(nextDeps, prevDeps)) { 16404 return prevState[0]; 16405 } 16406 } 16407 } 16408 16409 hook.memoizedState = [callback, nextDeps]; 16410 return callback; 16411 } 16412 16413 function mountMemo(nextCreate, deps) { 16414 var hook = mountWorkInProgressHook(); 16415 var nextDeps = deps === undefined ? null : deps; 16416 var nextValue = nextCreate(); 16417 hook.memoizedState = [nextValue, nextDeps]; 16418 return nextValue; 16419 } 16420 16421 function updateMemo(nextCreate, deps) { 16422 var hook = updateWorkInProgressHook(); 16423 var nextDeps = deps === undefined ? null : deps; 16424 var prevState = hook.memoizedState; 16425 16426 if (prevState !== null) { 16427 // Assume these are defined. If they're not, areHookInputsEqual will warn. 16428 if (nextDeps !== null) { 16429 var prevDeps = prevState[1]; 16430 16431 if (areHookInputsEqual(nextDeps, prevDeps)) { 16432 return prevState[0]; 16433 } 16434 } 16435 } 16436 16437 var nextValue = nextCreate(); 16438 hook.memoizedState = [nextValue, nextDeps]; 16439 return nextValue; 16440 } 16441 16442 function mountDeferredValue(value) { 16443 var hook = mountWorkInProgressHook(); 16444 hook.memoizedState = value; 16445 return value; 16446 } 16447 16448 function updateDeferredValue(value) { 16449 var hook = updateWorkInProgressHook(); 16450 var resolvedCurrentHook = currentHook; 16451 var prevValue = resolvedCurrentHook.memoizedState; 16452 return updateDeferredValueImpl(hook, prevValue, value); 16453 } 16454 16455 function rerenderDeferredValue(value) { 16456 var hook = updateWorkInProgressHook(); 16457 16458 if (currentHook === null) { 16459 // This is a rerender during a mount. 16460 hook.memoizedState = value; 16461 return value; 16462 } else { 16463 // This is a rerender during an update. 16464 var prevValue = currentHook.memoizedState; 16465 return updateDeferredValueImpl(hook, prevValue, value); 16466 } 16467 } 16468 16469 function updateDeferredValueImpl(hook, prevValue, value) { 16470 var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes); 16471 16472 if (shouldDeferValue) { 16473 // This is an urgent update. If the value has changed, keep using the 16474 // previous value and spawn a deferred render to update it later. 16475 if (!objectIs(value, prevValue)) { 16476 // Schedule a deferred render 16477 var deferredLane = claimNextTransitionLane(); 16478 currentlyRenderingFiber$1.lanes = mergeLanes(currentlyRenderingFiber$1.lanes, deferredLane); 16479 markSkippedUpdateLanes(deferredLane); // Set this to true to indicate that the rendered value is inconsistent 16480 // from the latest value. The name "baseState" doesn't really match how we 16481 // use it because we're reusing a state hook field instead of creating a 16482 // new one. 16483 16484 hook.baseState = true; 16485 } // Reuse the previous value 16486 16487 16488 return prevValue; 16489 } else { 16490 // This is not an urgent update, so we can use the latest value regardless 16491 // of what it is. No need to defer it. 16492 // However, if we're currently inside a spawned render, then we need to mark 16493 // this as an update to prevent the fiber from bailing out. 16494 // 16495 // `baseState` is true when the current value is different from the rendered 16496 // value. The name doesn't really match how we use it because we're reusing 16497 // a state hook field instead of creating a new one. 16498 if (hook.baseState) { 16499 // Flip this back to false. 16500 hook.baseState = false; 16501 markWorkInProgressReceivedUpdate(); 16502 } 16503 16504 hook.memoizedState = value; 16505 return value; 16506 } 16507 } 16508 16509 function startTransition(setPending, callback, options) { 16510 var previousPriority = getCurrentUpdatePriority(); 16511 setCurrentUpdatePriority(higherEventPriority(previousPriority, ContinuousEventPriority)); 16512 setPending(true); 16513 var prevTransition = ReactCurrentBatchConfig$2.transition; 16514 ReactCurrentBatchConfig$2.transition = {}; 16515 var currentTransition = ReactCurrentBatchConfig$2.transition; 16516 16517 { 16518 ReactCurrentBatchConfig$2.transition._updatedFibers = new Set(); 16519 } 16520 16521 try { 16522 setPending(false); 16523 callback(); 16524 } finally { 16525 setCurrentUpdatePriority(previousPriority); 16526 ReactCurrentBatchConfig$2.transition = prevTransition; 16527 16528 { 16529 if (prevTransition === null && currentTransition._updatedFibers) { 16530 var updatedFibersCount = currentTransition._updatedFibers.size; 16531 16532 if (updatedFibersCount > 10) { 16533 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.'); 16534 } 16535 16536 currentTransition._updatedFibers.clear(); 16537 } 16538 } 16539 } 16540 } 16541 16542 function mountTransition() { 16543 var _mountState = mountState(false), 16544 isPending = _mountState[0], 16545 setPending = _mountState[1]; // The `start` method never changes. 16546 16547 16548 var start = startTransition.bind(null, setPending); 16549 var hook = mountWorkInProgressHook(); 16550 hook.memoizedState = start; 16551 return [isPending, start]; 16552 } 16553 16554 function updateTransition() { 16555 var _updateState = updateState(), 16556 isPending = _updateState[0]; 16557 16558 var hook = updateWorkInProgressHook(); 16559 var start = hook.memoizedState; 16560 return [isPending, start]; 16561 } 16562 16563 function rerenderTransition() { 16564 var _rerenderState = rerenderState(), 16565 isPending = _rerenderState[0]; 16566 16567 var hook = updateWorkInProgressHook(); 16568 var start = hook.memoizedState; 16569 return [isPending, start]; 16570 } 16571 16572 var isUpdatingOpaqueValueInRenderPhase = false; 16573 function getIsUpdatingOpaqueValueInRenderPhaseInDEV() { 16574 { 16575 return isUpdatingOpaqueValueInRenderPhase; 16576 } 16577 } 16578 16579 function mountId() { 16580 var hook = mountWorkInProgressHook(); 16581 var root = getWorkInProgressRoot(); // TODO: In Fizz, id generation is specific to each server config. Maybe we 16582 // should do this in Fiber, too? Deferring this decision for now because 16583 // there's no other place to store the prefix except for an internal field on 16584 // the public createRoot object, which the fiber tree does not currently have 16585 // a reference to. 16586 16587 var identifierPrefix = root.identifierPrefix; 16588 var id; 16589 16590 if (getIsHydrating()) { 16591 var treeId = getTreeId(); // Use a captial R prefix for server-generated ids. 16592 16593 id = ':' + identifierPrefix + 'R' + treeId; // Unless this is the first id at this level, append a number at the end 16594 // that represents the position of this useId hook among all the useId 16595 // hooks for this fiber. 16596 16597 var localId = localIdCounter++; 16598 16599 if (localId > 0) { 16600 id += 'H' + localId.toString(32); 16601 } 16602 16603 id += ':'; 16604 } else { 16605 // Use a lowercase r prefix for client-generated ids. 16606 var globalClientId = globalClientIdCounter++; 16607 id = ':' + identifierPrefix + 'r' + globalClientId.toString(32) + ':'; 16608 } 16609 16610 hook.memoizedState = id; 16611 return id; 16612 } 16613 16614 function updateId() { 16615 var hook = updateWorkInProgressHook(); 16616 var id = hook.memoizedState; 16617 return id; 16618 } 16619 16620 function dispatchReducerAction(fiber, queue, action) { 16621 { 16622 if (typeof arguments[3] === 'function') { 16623 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().'); 16624 } 16625 } 16626 16627 var lane = requestUpdateLane(fiber); 16628 var update = { 16629 lane: lane, 16630 action: action, 16631 hasEagerState: false, 16632 eagerState: null, 16633 next: null 16634 }; 16635 16636 if (isRenderPhaseUpdate(fiber)) { 16637 enqueueRenderPhaseUpdate(queue, update); 16638 } else { 16639 var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); 16640 16641 if (root !== null) { 16642 var eventTime = requestEventTime(); 16643 scheduleUpdateOnFiber(root, fiber, lane, eventTime); 16644 entangleTransitionUpdate(root, queue, lane); 16645 } 16646 } 16647 16648 markUpdateInDevTools(fiber, lane); 16649 } 16650 16651 function dispatchSetState(fiber, queue, action) { 16652 { 16653 if (typeof arguments[3] === 'function') { 16654 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().'); 16655 } 16656 } 16657 16658 var lane = requestUpdateLane(fiber); 16659 var update = { 16660 lane: lane, 16661 action: action, 16662 hasEagerState: false, 16663 eagerState: null, 16664 next: null 16665 }; 16666 16667 if (isRenderPhaseUpdate(fiber)) { 16668 enqueueRenderPhaseUpdate(queue, update); 16669 } else { 16670 var alternate = fiber.alternate; 16671 16672 if (fiber.lanes === NoLanes && (alternate === null || alternate.lanes === NoLanes)) { 16673 // The queue is currently empty, which means we can eagerly compute the 16674 // next state before entering the render phase. If the new state is the 16675 // same as the current state, we may be able to bail out entirely. 16676 var lastRenderedReducer = queue.lastRenderedReducer; 16677 16678 if (lastRenderedReducer !== null) { 16679 var prevDispatcher; 16680 16681 { 16682 prevDispatcher = ReactCurrentDispatcher$1.current; 16683 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 16684 } 16685 16686 try { 16687 var currentState = queue.lastRenderedState; 16688 var eagerState = lastRenderedReducer(currentState, action); // Stash the eagerly computed state, and the reducer used to compute 16689 // it, on the update object. If the reducer hasn't changed by the 16690 // time we enter the render phase, then the eager state can be used 16691 // without calling the reducer again. 16692 16693 update.hasEagerState = true; 16694 update.eagerState = eagerState; 16695 16696 if (objectIs(eagerState, currentState)) { 16697 // Fast path. We can bail out without scheduling React to re-render. 16698 // It's still possible that we'll need to rebase this update later, 16699 // if the component re-renders for a different reason and by that 16700 // time the reducer has changed. 16701 // TODO: Do we still need to entangle transitions in this case? 16702 enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update, lane); 16703 return; 16704 } 16705 } catch (error) {// Suppress the error. It will throw again in the render phase. 16706 } finally { 16707 { 16708 ReactCurrentDispatcher$1.current = prevDispatcher; 16709 } 16710 } 16711 } 16712 } 16713 16714 var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); 16715 16716 if (root !== null) { 16717 var eventTime = requestEventTime(); 16718 scheduleUpdateOnFiber(root, fiber, lane, eventTime); 16719 entangleTransitionUpdate(root, queue, lane); 16720 } 16721 } 16722 16723 markUpdateInDevTools(fiber, lane); 16724 } 16725 16726 function isRenderPhaseUpdate(fiber) { 16727 var alternate = fiber.alternate; 16728 return fiber === currentlyRenderingFiber$1 || alternate !== null && alternate === currentlyRenderingFiber$1; 16729 } 16730 16731 function enqueueRenderPhaseUpdate(queue, update) { 16732 // This is a render phase update. Stash it in a lazily-created map of 16733 // queue -> linked list of updates. After this render pass, we'll restart 16734 // and apply the stashed updates on top of the work-in-progress hook. 16735 didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true; 16736 var pending = queue.pending; 16737 16738 if (pending === null) { 16739 // This is the first update. Create a circular list. 16740 update.next = update; 16741 } else { 16742 update.next = pending.next; 16743 pending.next = update; 16744 } 16745 16746 queue.pending = update; 16747 } // TODO: Move to ReactFiberConcurrentUpdates? 16748 16749 16750 function entangleTransitionUpdate(root, queue, lane) { 16751 if (isTransitionLane(lane)) { 16752 var queueLanes = queue.lanes; // If any entangled lanes are no longer pending on the root, then they 16753 // must have finished. We can remove them from the shared queue, which 16754 // represents a superset of the actually pending lanes. In some cases we 16755 // may entangle more than we need to, but that's OK. In fact it's worse if 16756 // we *don't* entangle when we should. 16757 16758 queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. 16759 16760 var newQueueLanes = mergeLanes(queueLanes, lane); 16761 queue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if 16762 // the lane finished since the last time we entangled it. So we need to 16763 // entangle it again, just to be sure. 16764 16765 markRootEntangled(root, newQueueLanes); 16766 } 16767 } 16768 16769 function markUpdateInDevTools(fiber, lane, action) { 16770 16771 { 16772 markStateUpdateScheduled(fiber, lane); 16773 } 16774 } 16775 16776 var ContextOnlyDispatcher = { 16777 readContext: readContext, 16778 useCallback: throwInvalidHookError, 16779 useContext: throwInvalidHookError, 16780 useEffect: throwInvalidHookError, 16781 useImperativeHandle: throwInvalidHookError, 16782 useInsertionEffect: throwInvalidHookError, 16783 useLayoutEffect: throwInvalidHookError, 16784 useMemo: throwInvalidHookError, 16785 useReducer: throwInvalidHookError, 16786 useRef: throwInvalidHookError, 16787 useState: throwInvalidHookError, 16788 useDebugValue: throwInvalidHookError, 16789 useDeferredValue: throwInvalidHookError, 16790 useTransition: throwInvalidHookError, 16791 useMutableSource: throwInvalidHookError, 16792 useSyncExternalStore: throwInvalidHookError, 16793 useId: throwInvalidHookError, 16794 unstable_isNewReconciler: enableNewReconciler 16795 }; 16796 16797 var HooksDispatcherOnMountInDEV = null; 16798 var HooksDispatcherOnMountWithHookTypesInDEV = null; 16799 var HooksDispatcherOnUpdateInDEV = null; 16800 var HooksDispatcherOnRerenderInDEV = null; 16801 var InvalidNestedHooksDispatcherOnMountInDEV = null; 16802 var InvalidNestedHooksDispatcherOnUpdateInDEV = null; 16803 var InvalidNestedHooksDispatcherOnRerenderInDEV = null; 16804 16805 { 16806 var warnInvalidContextAccess = function () { 16807 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().'); 16808 }; 16809 16810 var warnInvalidHookAccess = function () { 16811 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'); 16812 }; 16813 16814 HooksDispatcherOnMountInDEV = { 16815 readContext: function (context) { 16816 return readContext(context); 16817 }, 16818 useCallback: function (callback, deps) { 16819 currentHookNameInDev = 'useCallback'; 16820 mountHookTypesDev(); 16821 checkDepsAreArrayDev(deps); 16822 return mountCallback(callback, deps); 16823 }, 16824 useContext: function (context) { 16825 currentHookNameInDev = 'useContext'; 16826 mountHookTypesDev(); 16827 return readContext(context); 16828 }, 16829 useEffect: function (create, deps) { 16830 currentHookNameInDev = 'useEffect'; 16831 mountHookTypesDev(); 16832 checkDepsAreArrayDev(deps); 16833 return mountEffect(create, deps); 16834 }, 16835 useImperativeHandle: function (ref, create, deps) { 16836 currentHookNameInDev = 'useImperativeHandle'; 16837 mountHookTypesDev(); 16838 checkDepsAreArrayDev(deps); 16839 return mountImperativeHandle(ref, create, deps); 16840 }, 16841 useInsertionEffect: function (create, deps) { 16842 currentHookNameInDev = 'useInsertionEffect'; 16843 mountHookTypesDev(); 16844 checkDepsAreArrayDev(deps); 16845 return mountInsertionEffect(create, deps); 16846 }, 16847 useLayoutEffect: function (create, deps) { 16848 currentHookNameInDev = 'useLayoutEffect'; 16849 mountHookTypesDev(); 16850 checkDepsAreArrayDev(deps); 16851 return mountLayoutEffect(create, deps); 16852 }, 16853 useMemo: function (create, deps) { 16854 currentHookNameInDev = 'useMemo'; 16855 mountHookTypesDev(); 16856 checkDepsAreArrayDev(deps); 16857 var prevDispatcher = ReactCurrentDispatcher$1.current; 16858 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 16859 16860 try { 16861 return mountMemo(create, deps); 16862 } finally { 16863 ReactCurrentDispatcher$1.current = prevDispatcher; 16864 } 16865 }, 16866 useReducer: function (reducer, initialArg, init) { 16867 currentHookNameInDev = 'useReducer'; 16868 mountHookTypesDev(); 16869 var prevDispatcher = ReactCurrentDispatcher$1.current; 16870 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 16871 16872 try { 16873 return mountReducer(reducer, initialArg, init); 16874 } finally { 16875 ReactCurrentDispatcher$1.current = prevDispatcher; 16876 } 16877 }, 16878 useRef: function (initialValue) { 16879 currentHookNameInDev = 'useRef'; 16880 mountHookTypesDev(); 16881 return mountRef(initialValue); 16882 }, 16883 useState: function (initialState) { 16884 currentHookNameInDev = 'useState'; 16885 mountHookTypesDev(); 16886 var prevDispatcher = ReactCurrentDispatcher$1.current; 16887 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 16888 16889 try { 16890 return mountState(initialState); 16891 } finally { 16892 ReactCurrentDispatcher$1.current = prevDispatcher; 16893 } 16894 }, 16895 useDebugValue: function (value, formatterFn) { 16896 currentHookNameInDev = 'useDebugValue'; 16897 mountHookTypesDev(); 16898 return mountDebugValue(); 16899 }, 16900 useDeferredValue: function (value) { 16901 currentHookNameInDev = 'useDeferredValue'; 16902 mountHookTypesDev(); 16903 return mountDeferredValue(value); 16904 }, 16905 useTransition: function () { 16906 currentHookNameInDev = 'useTransition'; 16907 mountHookTypesDev(); 16908 return mountTransition(); 16909 }, 16910 useMutableSource: function (source, getSnapshot, subscribe) { 16911 currentHookNameInDev = 'useMutableSource'; 16912 mountHookTypesDev(); 16913 return mountMutableSource(); 16914 }, 16915 useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { 16916 currentHookNameInDev = 'useSyncExternalStore'; 16917 mountHookTypesDev(); 16918 return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); 16919 }, 16920 useId: function () { 16921 currentHookNameInDev = 'useId'; 16922 mountHookTypesDev(); 16923 return mountId(); 16924 }, 16925 unstable_isNewReconciler: enableNewReconciler 16926 }; 16927 16928 HooksDispatcherOnMountWithHookTypesInDEV = { 16929 readContext: function (context) { 16930 return readContext(context); 16931 }, 16932 useCallback: function (callback, deps) { 16933 currentHookNameInDev = 'useCallback'; 16934 updateHookTypesDev(); 16935 return mountCallback(callback, deps); 16936 }, 16937 useContext: function (context) { 16938 currentHookNameInDev = 'useContext'; 16939 updateHookTypesDev(); 16940 return readContext(context); 16941 }, 16942 useEffect: function (create, deps) { 16943 currentHookNameInDev = 'useEffect'; 16944 updateHookTypesDev(); 16945 return mountEffect(create, deps); 16946 }, 16947 useImperativeHandle: function (ref, create, deps) { 16948 currentHookNameInDev = 'useImperativeHandle'; 16949 updateHookTypesDev(); 16950 return mountImperativeHandle(ref, create, deps); 16951 }, 16952 useInsertionEffect: function (create, deps) { 16953 currentHookNameInDev = 'useInsertionEffect'; 16954 updateHookTypesDev(); 16955 return mountInsertionEffect(create, deps); 16956 }, 16957 useLayoutEffect: function (create, deps) { 16958 currentHookNameInDev = 'useLayoutEffect'; 16959 updateHookTypesDev(); 16960 return mountLayoutEffect(create, deps); 16961 }, 16962 useMemo: function (create, deps) { 16963 currentHookNameInDev = 'useMemo'; 16964 updateHookTypesDev(); 16965 var prevDispatcher = ReactCurrentDispatcher$1.current; 16966 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 16967 16968 try { 16969 return mountMemo(create, deps); 16970 } finally { 16971 ReactCurrentDispatcher$1.current = prevDispatcher; 16972 } 16973 }, 16974 useReducer: function (reducer, initialArg, init) { 16975 currentHookNameInDev = 'useReducer'; 16976 updateHookTypesDev(); 16977 var prevDispatcher = ReactCurrentDispatcher$1.current; 16978 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 16979 16980 try { 16981 return mountReducer(reducer, initialArg, init); 16982 } finally { 16983 ReactCurrentDispatcher$1.current = prevDispatcher; 16984 } 16985 }, 16986 useRef: function (initialValue) { 16987 currentHookNameInDev = 'useRef'; 16988 updateHookTypesDev(); 16989 return mountRef(initialValue); 16990 }, 16991 useState: function (initialState) { 16992 currentHookNameInDev = 'useState'; 16993 updateHookTypesDev(); 16994 var prevDispatcher = ReactCurrentDispatcher$1.current; 16995 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 16996 16997 try { 16998 return mountState(initialState); 16999 } finally { 17000 ReactCurrentDispatcher$1.current = prevDispatcher; 17001 } 17002 }, 17003 useDebugValue: function (value, formatterFn) { 17004 currentHookNameInDev = 'useDebugValue'; 17005 updateHookTypesDev(); 17006 return mountDebugValue(); 17007 }, 17008 useDeferredValue: function (value) { 17009 currentHookNameInDev = 'useDeferredValue'; 17010 updateHookTypesDev(); 17011 return mountDeferredValue(value); 17012 }, 17013 useTransition: function () { 17014 currentHookNameInDev = 'useTransition'; 17015 updateHookTypesDev(); 17016 return mountTransition(); 17017 }, 17018 useMutableSource: function (source, getSnapshot, subscribe) { 17019 currentHookNameInDev = 'useMutableSource'; 17020 updateHookTypesDev(); 17021 return mountMutableSource(); 17022 }, 17023 useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { 17024 currentHookNameInDev = 'useSyncExternalStore'; 17025 updateHookTypesDev(); 17026 return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); 17027 }, 17028 useId: function () { 17029 currentHookNameInDev = 'useId'; 17030 updateHookTypesDev(); 17031 return mountId(); 17032 }, 17033 unstable_isNewReconciler: enableNewReconciler 17034 }; 17035 17036 HooksDispatcherOnUpdateInDEV = { 17037 readContext: function (context) { 17038 return readContext(context); 17039 }, 17040 useCallback: function (callback, deps) { 17041 currentHookNameInDev = 'useCallback'; 17042 updateHookTypesDev(); 17043 return updateCallback(callback, deps); 17044 }, 17045 useContext: function (context) { 17046 currentHookNameInDev = 'useContext'; 17047 updateHookTypesDev(); 17048 return readContext(context); 17049 }, 17050 useEffect: function (create, deps) { 17051 currentHookNameInDev = 'useEffect'; 17052 updateHookTypesDev(); 17053 return updateEffect(create, deps); 17054 }, 17055 useImperativeHandle: function (ref, create, deps) { 17056 currentHookNameInDev = 'useImperativeHandle'; 17057 updateHookTypesDev(); 17058 return updateImperativeHandle(ref, create, deps); 17059 }, 17060 useInsertionEffect: function (create, deps) { 17061 currentHookNameInDev = 'useInsertionEffect'; 17062 updateHookTypesDev(); 17063 return updateInsertionEffect(create, deps); 17064 }, 17065 useLayoutEffect: function (create, deps) { 17066 currentHookNameInDev = 'useLayoutEffect'; 17067 updateHookTypesDev(); 17068 return updateLayoutEffect(create, deps); 17069 }, 17070 useMemo: function (create, deps) { 17071 currentHookNameInDev = 'useMemo'; 17072 updateHookTypesDev(); 17073 var prevDispatcher = ReactCurrentDispatcher$1.current; 17074 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 17075 17076 try { 17077 return updateMemo(create, deps); 17078 } finally { 17079 ReactCurrentDispatcher$1.current = prevDispatcher; 17080 } 17081 }, 17082 useReducer: function (reducer, initialArg, init) { 17083 currentHookNameInDev = 'useReducer'; 17084 updateHookTypesDev(); 17085 var prevDispatcher = ReactCurrentDispatcher$1.current; 17086 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 17087 17088 try { 17089 return updateReducer(reducer, initialArg, init); 17090 } finally { 17091 ReactCurrentDispatcher$1.current = prevDispatcher; 17092 } 17093 }, 17094 useRef: function (initialValue) { 17095 currentHookNameInDev = 'useRef'; 17096 updateHookTypesDev(); 17097 return updateRef(); 17098 }, 17099 useState: function (initialState) { 17100 currentHookNameInDev = 'useState'; 17101 updateHookTypesDev(); 17102 var prevDispatcher = ReactCurrentDispatcher$1.current; 17103 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 17104 17105 try { 17106 return updateState(initialState); 17107 } finally { 17108 ReactCurrentDispatcher$1.current = prevDispatcher; 17109 } 17110 }, 17111 useDebugValue: function (value, formatterFn) { 17112 currentHookNameInDev = 'useDebugValue'; 17113 updateHookTypesDev(); 17114 return updateDebugValue(); 17115 }, 17116 useDeferredValue: function (value) { 17117 currentHookNameInDev = 'useDeferredValue'; 17118 updateHookTypesDev(); 17119 return updateDeferredValue(value); 17120 }, 17121 useTransition: function () { 17122 currentHookNameInDev = 'useTransition'; 17123 updateHookTypesDev(); 17124 return updateTransition(); 17125 }, 17126 useMutableSource: function (source, getSnapshot, subscribe) { 17127 currentHookNameInDev = 'useMutableSource'; 17128 updateHookTypesDev(); 17129 return updateMutableSource(); 17130 }, 17131 useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { 17132 currentHookNameInDev = 'useSyncExternalStore'; 17133 updateHookTypesDev(); 17134 return updateSyncExternalStore(subscribe, getSnapshot); 17135 }, 17136 useId: function () { 17137 currentHookNameInDev = 'useId'; 17138 updateHookTypesDev(); 17139 return updateId(); 17140 }, 17141 unstable_isNewReconciler: enableNewReconciler 17142 }; 17143 17144 HooksDispatcherOnRerenderInDEV = { 17145 readContext: function (context) { 17146 return readContext(context); 17147 }, 17148 useCallback: function (callback, deps) { 17149 currentHookNameInDev = 'useCallback'; 17150 updateHookTypesDev(); 17151 return updateCallback(callback, deps); 17152 }, 17153 useContext: function (context) { 17154 currentHookNameInDev = 'useContext'; 17155 updateHookTypesDev(); 17156 return readContext(context); 17157 }, 17158 useEffect: function (create, deps) { 17159 currentHookNameInDev = 'useEffect'; 17160 updateHookTypesDev(); 17161 return updateEffect(create, deps); 17162 }, 17163 useImperativeHandle: function (ref, create, deps) { 17164 currentHookNameInDev = 'useImperativeHandle'; 17165 updateHookTypesDev(); 17166 return updateImperativeHandle(ref, create, deps); 17167 }, 17168 useInsertionEffect: function (create, deps) { 17169 currentHookNameInDev = 'useInsertionEffect'; 17170 updateHookTypesDev(); 17171 return updateInsertionEffect(create, deps); 17172 }, 17173 useLayoutEffect: function (create, deps) { 17174 currentHookNameInDev = 'useLayoutEffect'; 17175 updateHookTypesDev(); 17176 return updateLayoutEffect(create, deps); 17177 }, 17178 useMemo: function (create, deps) { 17179 currentHookNameInDev = 'useMemo'; 17180 updateHookTypesDev(); 17181 var prevDispatcher = ReactCurrentDispatcher$1.current; 17182 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnRerenderInDEV; 17183 17184 try { 17185 return updateMemo(create, deps); 17186 } finally { 17187 ReactCurrentDispatcher$1.current = prevDispatcher; 17188 } 17189 }, 17190 useReducer: function (reducer, initialArg, init) { 17191 currentHookNameInDev = 'useReducer'; 17192 updateHookTypesDev(); 17193 var prevDispatcher = ReactCurrentDispatcher$1.current; 17194 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnRerenderInDEV; 17195 17196 try { 17197 return rerenderReducer(reducer, initialArg, init); 17198 } finally { 17199 ReactCurrentDispatcher$1.current = prevDispatcher; 17200 } 17201 }, 17202 useRef: function (initialValue) { 17203 currentHookNameInDev = 'useRef'; 17204 updateHookTypesDev(); 17205 return updateRef(); 17206 }, 17207 useState: function (initialState) { 17208 currentHookNameInDev = 'useState'; 17209 updateHookTypesDev(); 17210 var prevDispatcher = ReactCurrentDispatcher$1.current; 17211 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnRerenderInDEV; 17212 17213 try { 17214 return rerenderState(initialState); 17215 } finally { 17216 ReactCurrentDispatcher$1.current = prevDispatcher; 17217 } 17218 }, 17219 useDebugValue: function (value, formatterFn) { 17220 currentHookNameInDev = 'useDebugValue'; 17221 updateHookTypesDev(); 17222 return updateDebugValue(); 17223 }, 17224 useDeferredValue: function (value) { 17225 currentHookNameInDev = 'useDeferredValue'; 17226 updateHookTypesDev(); 17227 return rerenderDeferredValue(value); 17228 }, 17229 useTransition: function () { 17230 currentHookNameInDev = 'useTransition'; 17231 updateHookTypesDev(); 17232 return rerenderTransition(); 17233 }, 17234 useMutableSource: function (source, getSnapshot, subscribe) { 17235 currentHookNameInDev = 'useMutableSource'; 17236 updateHookTypesDev(); 17237 return updateMutableSource(); 17238 }, 17239 useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { 17240 currentHookNameInDev = 'useSyncExternalStore'; 17241 updateHookTypesDev(); 17242 return updateSyncExternalStore(subscribe, getSnapshot); 17243 }, 17244 useId: function () { 17245 currentHookNameInDev = 'useId'; 17246 updateHookTypesDev(); 17247 return updateId(); 17248 }, 17249 unstable_isNewReconciler: enableNewReconciler 17250 }; 17251 17252 InvalidNestedHooksDispatcherOnMountInDEV = { 17253 readContext: function (context) { 17254 warnInvalidContextAccess(); 17255 return readContext(context); 17256 }, 17257 useCallback: function (callback, deps) { 17258 currentHookNameInDev = 'useCallback'; 17259 warnInvalidHookAccess(); 17260 mountHookTypesDev(); 17261 return mountCallback(callback, deps); 17262 }, 17263 useContext: function (context) { 17264 currentHookNameInDev = 'useContext'; 17265 warnInvalidHookAccess(); 17266 mountHookTypesDev(); 17267 return readContext(context); 17268 }, 17269 useEffect: function (create, deps) { 17270 currentHookNameInDev = 'useEffect'; 17271 warnInvalidHookAccess(); 17272 mountHookTypesDev(); 17273 return mountEffect(create, deps); 17274 }, 17275 useImperativeHandle: function (ref, create, deps) { 17276 currentHookNameInDev = 'useImperativeHandle'; 17277 warnInvalidHookAccess(); 17278 mountHookTypesDev(); 17279 return mountImperativeHandle(ref, create, deps); 17280 }, 17281 useInsertionEffect: function (create, deps) { 17282 currentHookNameInDev = 'useInsertionEffect'; 17283 warnInvalidHookAccess(); 17284 mountHookTypesDev(); 17285 return mountInsertionEffect(create, deps); 17286 }, 17287 useLayoutEffect: function (create, deps) { 17288 currentHookNameInDev = 'useLayoutEffect'; 17289 warnInvalidHookAccess(); 17290 mountHookTypesDev(); 17291 return mountLayoutEffect(create, deps); 17292 }, 17293 useMemo: function (create, deps) { 17294 currentHookNameInDev = 'useMemo'; 17295 warnInvalidHookAccess(); 17296 mountHookTypesDev(); 17297 var prevDispatcher = ReactCurrentDispatcher$1.current; 17298 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 17299 17300 try { 17301 return mountMemo(create, deps); 17302 } finally { 17303 ReactCurrentDispatcher$1.current = prevDispatcher; 17304 } 17305 }, 17306 useReducer: function (reducer, initialArg, init) { 17307 currentHookNameInDev = 'useReducer'; 17308 warnInvalidHookAccess(); 17309 mountHookTypesDev(); 17310 var prevDispatcher = ReactCurrentDispatcher$1.current; 17311 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 17312 17313 try { 17314 return mountReducer(reducer, initialArg, init); 17315 } finally { 17316 ReactCurrentDispatcher$1.current = prevDispatcher; 17317 } 17318 }, 17319 useRef: function (initialValue) { 17320 currentHookNameInDev = 'useRef'; 17321 warnInvalidHookAccess(); 17322 mountHookTypesDev(); 17323 return mountRef(initialValue); 17324 }, 17325 useState: function (initialState) { 17326 currentHookNameInDev = 'useState'; 17327 warnInvalidHookAccess(); 17328 mountHookTypesDev(); 17329 var prevDispatcher = ReactCurrentDispatcher$1.current; 17330 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 17331 17332 try { 17333 return mountState(initialState); 17334 } finally { 17335 ReactCurrentDispatcher$1.current = prevDispatcher; 17336 } 17337 }, 17338 useDebugValue: function (value, formatterFn) { 17339 currentHookNameInDev = 'useDebugValue'; 17340 warnInvalidHookAccess(); 17341 mountHookTypesDev(); 17342 return mountDebugValue(); 17343 }, 17344 useDeferredValue: function (value) { 17345 currentHookNameInDev = 'useDeferredValue'; 17346 warnInvalidHookAccess(); 17347 mountHookTypesDev(); 17348 return mountDeferredValue(value); 17349 }, 17350 useTransition: function () { 17351 currentHookNameInDev = 'useTransition'; 17352 warnInvalidHookAccess(); 17353 mountHookTypesDev(); 17354 return mountTransition(); 17355 }, 17356 useMutableSource: function (source, getSnapshot, subscribe) { 17357 currentHookNameInDev = 'useMutableSource'; 17358 warnInvalidHookAccess(); 17359 mountHookTypesDev(); 17360 return mountMutableSource(); 17361 }, 17362 useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { 17363 currentHookNameInDev = 'useSyncExternalStore'; 17364 warnInvalidHookAccess(); 17365 mountHookTypesDev(); 17366 return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); 17367 }, 17368 useId: function () { 17369 currentHookNameInDev = 'useId'; 17370 warnInvalidHookAccess(); 17371 mountHookTypesDev(); 17372 return mountId(); 17373 }, 17374 unstable_isNewReconciler: enableNewReconciler 17375 }; 17376 17377 InvalidNestedHooksDispatcherOnUpdateInDEV = { 17378 readContext: function (context) { 17379 warnInvalidContextAccess(); 17380 return readContext(context); 17381 }, 17382 useCallback: function (callback, deps) { 17383 currentHookNameInDev = 'useCallback'; 17384 warnInvalidHookAccess(); 17385 updateHookTypesDev(); 17386 return updateCallback(callback, deps); 17387 }, 17388 useContext: function (context) { 17389 currentHookNameInDev = 'useContext'; 17390 warnInvalidHookAccess(); 17391 updateHookTypesDev(); 17392 return readContext(context); 17393 }, 17394 useEffect: function (create, deps) { 17395 currentHookNameInDev = 'useEffect'; 17396 warnInvalidHookAccess(); 17397 updateHookTypesDev(); 17398 return updateEffect(create, deps); 17399 }, 17400 useImperativeHandle: function (ref, create, deps) { 17401 currentHookNameInDev = 'useImperativeHandle'; 17402 warnInvalidHookAccess(); 17403 updateHookTypesDev(); 17404 return updateImperativeHandle(ref, create, deps); 17405 }, 17406 useInsertionEffect: function (create, deps) { 17407 currentHookNameInDev = 'useInsertionEffect'; 17408 warnInvalidHookAccess(); 17409 updateHookTypesDev(); 17410 return updateInsertionEffect(create, deps); 17411 }, 17412 useLayoutEffect: function (create, deps) { 17413 currentHookNameInDev = 'useLayoutEffect'; 17414 warnInvalidHookAccess(); 17415 updateHookTypesDev(); 17416 return updateLayoutEffect(create, deps); 17417 }, 17418 useMemo: function (create, deps) { 17419 currentHookNameInDev = 'useMemo'; 17420 warnInvalidHookAccess(); 17421 updateHookTypesDev(); 17422 var prevDispatcher = ReactCurrentDispatcher$1.current; 17423 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 17424 17425 try { 17426 return updateMemo(create, deps); 17427 } finally { 17428 ReactCurrentDispatcher$1.current = prevDispatcher; 17429 } 17430 }, 17431 useReducer: function (reducer, initialArg, init) { 17432 currentHookNameInDev = 'useReducer'; 17433 warnInvalidHookAccess(); 17434 updateHookTypesDev(); 17435 var prevDispatcher = ReactCurrentDispatcher$1.current; 17436 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 17437 17438 try { 17439 return updateReducer(reducer, initialArg, init); 17440 } finally { 17441 ReactCurrentDispatcher$1.current = prevDispatcher; 17442 } 17443 }, 17444 useRef: function (initialValue) { 17445 currentHookNameInDev = 'useRef'; 17446 warnInvalidHookAccess(); 17447 updateHookTypesDev(); 17448 return updateRef(); 17449 }, 17450 useState: function (initialState) { 17451 currentHookNameInDev = 'useState'; 17452 warnInvalidHookAccess(); 17453 updateHookTypesDev(); 17454 var prevDispatcher = ReactCurrentDispatcher$1.current; 17455 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 17456 17457 try { 17458 return updateState(initialState); 17459 } finally { 17460 ReactCurrentDispatcher$1.current = prevDispatcher; 17461 } 17462 }, 17463 useDebugValue: function (value, formatterFn) { 17464 currentHookNameInDev = 'useDebugValue'; 17465 warnInvalidHookAccess(); 17466 updateHookTypesDev(); 17467 return updateDebugValue(); 17468 }, 17469 useDeferredValue: function (value) { 17470 currentHookNameInDev = 'useDeferredValue'; 17471 warnInvalidHookAccess(); 17472 updateHookTypesDev(); 17473 return updateDeferredValue(value); 17474 }, 17475 useTransition: function () { 17476 currentHookNameInDev = 'useTransition'; 17477 warnInvalidHookAccess(); 17478 updateHookTypesDev(); 17479 return updateTransition(); 17480 }, 17481 useMutableSource: function (source, getSnapshot, subscribe) { 17482 currentHookNameInDev = 'useMutableSource'; 17483 warnInvalidHookAccess(); 17484 updateHookTypesDev(); 17485 return updateMutableSource(); 17486 }, 17487 useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { 17488 currentHookNameInDev = 'useSyncExternalStore'; 17489 warnInvalidHookAccess(); 17490 updateHookTypesDev(); 17491 return updateSyncExternalStore(subscribe, getSnapshot); 17492 }, 17493 useId: function () { 17494 currentHookNameInDev = 'useId'; 17495 warnInvalidHookAccess(); 17496 updateHookTypesDev(); 17497 return updateId(); 17498 }, 17499 unstable_isNewReconciler: enableNewReconciler 17500 }; 17501 17502 InvalidNestedHooksDispatcherOnRerenderInDEV = { 17503 readContext: function (context) { 17504 warnInvalidContextAccess(); 17505 return readContext(context); 17506 }, 17507 useCallback: function (callback, deps) { 17508 currentHookNameInDev = 'useCallback'; 17509 warnInvalidHookAccess(); 17510 updateHookTypesDev(); 17511 return updateCallback(callback, deps); 17512 }, 17513 useContext: function (context) { 17514 currentHookNameInDev = 'useContext'; 17515 warnInvalidHookAccess(); 17516 updateHookTypesDev(); 17517 return readContext(context); 17518 }, 17519 useEffect: function (create, deps) { 17520 currentHookNameInDev = 'useEffect'; 17521 warnInvalidHookAccess(); 17522 updateHookTypesDev(); 17523 return updateEffect(create, deps); 17524 }, 17525 useImperativeHandle: function (ref, create, deps) { 17526 currentHookNameInDev = 'useImperativeHandle'; 17527 warnInvalidHookAccess(); 17528 updateHookTypesDev(); 17529 return updateImperativeHandle(ref, create, deps); 17530 }, 17531 useInsertionEffect: function (create, deps) { 17532 currentHookNameInDev = 'useInsertionEffect'; 17533 warnInvalidHookAccess(); 17534 updateHookTypesDev(); 17535 return updateInsertionEffect(create, deps); 17536 }, 17537 useLayoutEffect: function (create, deps) { 17538 currentHookNameInDev = 'useLayoutEffect'; 17539 warnInvalidHookAccess(); 17540 updateHookTypesDev(); 17541 return updateLayoutEffect(create, deps); 17542 }, 17543 useMemo: function (create, deps) { 17544 currentHookNameInDev = 'useMemo'; 17545 warnInvalidHookAccess(); 17546 updateHookTypesDev(); 17547 var prevDispatcher = ReactCurrentDispatcher$1.current; 17548 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 17549 17550 try { 17551 return updateMemo(create, deps); 17552 } finally { 17553 ReactCurrentDispatcher$1.current = prevDispatcher; 17554 } 17555 }, 17556 useReducer: function (reducer, initialArg, init) { 17557 currentHookNameInDev = 'useReducer'; 17558 warnInvalidHookAccess(); 17559 updateHookTypesDev(); 17560 var prevDispatcher = ReactCurrentDispatcher$1.current; 17561 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 17562 17563 try { 17564 return rerenderReducer(reducer, initialArg, init); 17565 } finally { 17566 ReactCurrentDispatcher$1.current = prevDispatcher; 17567 } 17568 }, 17569 useRef: function (initialValue) { 17570 currentHookNameInDev = 'useRef'; 17571 warnInvalidHookAccess(); 17572 updateHookTypesDev(); 17573 return updateRef(); 17574 }, 17575 useState: function (initialState) { 17576 currentHookNameInDev = 'useState'; 17577 warnInvalidHookAccess(); 17578 updateHookTypesDev(); 17579 var prevDispatcher = ReactCurrentDispatcher$1.current; 17580 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 17581 17582 try { 17583 return rerenderState(initialState); 17584 } finally { 17585 ReactCurrentDispatcher$1.current = prevDispatcher; 17586 } 17587 }, 17588 useDebugValue: function (value, formatterFn) { 17589 currentHookNameInDev = 'useDebugValue'; 17590 warnInvalidHookAccess(); 17591 updateHookTypesDev(); 17592 return updateDebugValue(); 17593 }, 17594 useDeferredValue: function (value) { 17595 currentHookNameInDev = 'useDeferredValue'; 17596 warnInvalidHookAccess(); 17597 updateHookTypesDev(); 17598 return rerenderDeferredValue(value); 17599 }, 17600 useTransition: function () { 17601 currentHookNameInDev = 'useTransition'; 17602 warnInvalidHookAccess(); 17603 updateHookTypesDev(); 17604 return rerenderTransition(); 17605 }, 17606 useMutableSource: function (source, getSnapshot, subscribe) { 17607 currentHookNameInDev = 'useMutableSource'; 17608 warnInvalidHookAccess(); 17609 updateHookTypesDev(); 17610 return updateMutableSource(); 17611 }, 17612 useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { 17613 currentHookNameInDev = 'useSyncExternalStore'; 17614 warnInvalidHookAccess(); 17615 updateHookTypesDev(); 17616 return updateSyncExternalStore(subscribe, getSnapshot); 17617 }, 17618 useId: function () { 17619 currentHookNameInDev = 'useId'; 17620 warnInvalidHookAccess(); 17621 updateHookTypesDev(); 17622 return updateId(); 17623 }, 17624 unstable_isNewReconciler: enableNewReconciler 17625 }; 17626 } 17627 17628 var now$1 = unstable_now; 17629 var commitTime = 0; 17630 var layoutEffectStartTime = -1; 17631 var profilerStartTime = -1; 17632 var passiveEffectStartTime = -1; 17633 /** 17634 * Tracks whether the current update was a nested/cascading update (scheduled from a layout effect). 17635 * 17636 * The overall sequence is: 17637 * 1. render 17638 * 2. commit (and call `onRender`, `onCommit`) 17639 * 3. check for nested updates 17640 * 4. flush passive effects (and call `onPostCommit`) 17641 * 17642 * Nested updates are identified in step 3 above, 17643 * but step 4 still applies to the work that was just committed. 17644 * We use two flags to track nested updates then: 17645 * one tracks whether the upcoming update is a nested update, 17646 * and the other tracks whether the current update was a nested update. 17647 * The first value gets synced to the second at the start of the render phase. 17648 */ 17649 17650 var currentUpdateIsNested = false; 17651 var nestedUpdateScheduled = false; 17652 17653 function isCurrentUpdateNested() { 17654 return currentUpdateIsNested; 17655 } 17656 17657 function markNestedUpdateScheduled() { 17658 { 17659 nestedUpdateScheduled = true; 17660 } 17661 } 17662 17663 function resetNestedUpdateFlag() { 17664 { 17665 currentUpdateIsNested = false; 17666 nestedUpdateScheduled = false; 17667 } 17668 } 17669 17670 function syncNestedUpdateFlag() { 17671 { 17672 currentUpdateIsNested = nestedUpdateScheduled; 17673 nestedUpdateScheduled = false; 17674 } 17675 } 17676 17677 function getCommitTime() { 17678 return commitTime; 17679 } 17680 17681 function recordCommitTime() { 17682 17683 commitTime = now$1(); 17684 } 17685 17686 function startProfilerTimer(fiber) { 17687 17688 profilerStartTime = now$1(); 17689 17690 if (fiber.actualStartTime < 0) { 17691 fiber.actualStartTime = now$1(); 17692 } 17693 } 17694 17695 function stopProfilerTimerIfRunning(fiber) { 17696 17697 profilerStartTime = -1; 17698 } 17699 17700 function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { 17701 17702 if (profilerStartTime >= 0) { 17703 var elapsedTime = now$1() - profilerStartTime; 17704 fiber.actualDuration += elapsedTime; 17705 17706 if (overrideBaseTime) { 17707 fiber.selfBaseDuration = elapsedTime; 17708 } 17709 17710 profilerStartTime = -1; 17711 } 17712 } 17713 17714 function recordLayoutEffectDuration(fiber) { 17715 17716 if (layoutEffectStartTime >= 0) { 17717 var elapsedTime = now$1() - layoutEffectStartTime; 17718 layoutEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor 17719 // Or the root (for the DevTools Profiler to read) 17720 17721 var parentFiber = fiber.return; 17722 17723 while (parentFiber !== null) { 17724 switch (parentFiber.tag) { 17725 case HostRoot: 17726 var root = parentFiber.stateNode; 17727 root.effectDuration += elapsedTime; 17728 return; 17729 17730 case Profiler: 17731 var parentStateNode = parentFiber.stateNode; 17732 parentStateNode.effectDuration += elapsedTime; 17733 return; 17734 } 17735 17736 parentFiber = parentFiber.return; 17737 } 17738 } 17739 } 17740 17741 function recordPassiveEffectDuration(fiber) { 17742 17743 if (passiveEffectStartTime >= 0) { 17744 var elapsedTime = now$1() - passiveEffectStartTime; 17745 passiveEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor 17746 // Or the root (for the DevTools Profiler to read) 17747 17748 var parentFiber = fiber.return; 17749 17750 while (parentFiber !== null) { 17751 switch (parentFiber.tag) { 17752 case HostRoot: 17753 var root = parentFiber.stateNode; 17754 17755 if (root !== null) { 17756 root.passiveEffectDuration += elapsedTime; 17757 } 17758 17759 return; 17760 17761 case Profiler: 17762 var parentStateNode = parentFiber.stateNode; 17763 17764 if (parentStateNode !== null) { 17765 // Detached fibers have their state node cleared out. 17766 // In this case, the return pointer is also cleared out, 17767 // so we won't be able to report the time spent in this Profiler's subtree. 17768 parentStateNode.passiveEffectDuration += elapsedTime; 17769 } 17770 17771 return; 17772 } 17773 17774 parentFiber = parentFiber.return; 17775 } 17776 } 17777 } 17778 17779 function startLayoutEffectTimer() { 17780 17781 layoutEffectStartTime = now$1(); 17782 } 17783 17784 function startPassiveEffectTimer() { 17785 17786 passiveEffectStartTime = now$1(); 17787 } 17788 17789 function transferActualDuration(fiber) { 17790 // Transfer time spent rendering these children so we don't lose it 17791 // after we rerender. This is used as a helper in special cases 17792 // where we should count the work of multiple passes. 17793 var child = fiber.child; 17794 17795 while (child) { 17796 fiber.actualDuration += child.actualDuration; 17797 child = child.sibling; 17798 } 17799 } 17800 17801 function resolveDefaultProps(Component, baseProps) { 17802 if (Component && Component.defaultProps) { 17803 // Resolve default props. Taken from ReactElement 17804 var props = assign({}, baseProps); 17805 var defaultProps = Component.defaultProps; 17806 17807 for (var propName in defaultProps) { 17808 if (props[propName] === undefined) { 17809 props[propName] = defaultProps[propName]; 17810 } 17811 } 17812 17813 return props; 17814 } 17815 17816 return baseProps; 17817 } 17818 17819 var fakeInternalInstance = {}; 17820 var didWarnAboutStateAssignmentForComponent; 17821 var didWarnAboutUninitializedState; 17822 var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate; 17823 var didWarnAboutLegacyLifecyclesAndDerivedState; 17824 var didWarnAboutUndefinedDerivedState; 17825 var warnOnUndefinedDerivedState; 17826 var warnOnInvalidCallback; 17827 var didWarnAboutDirectlyAssigningPropsToState; 17828 var didWarnAboutContextTypeAndContextTypes; 17829 var didWarnAboutInvalidateContextType; 17830 var didWarnAboutLegacyContext$1; 17831 17832 { 17833 didWarnAboutStateAssignmentForComponent = new Set(); 17834 didWarnAboutUninitializedState = new Set(); 17835 didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set(); 17836 didWarnAboutLegacyLifecyclesAndDerivedState = new Set(); 17837 didWarnAboutDirectlyAssigningPropsToState = new Set(); 17838 didWarnAboutUndefinedDerivedState = new Set(); 17839 didWarnAboutContextTypeAndContextTypes = new Set(); 17840 didWarnAboutInvalidateContextType = new Set(); 17841 didWarnAboutLegacyContext$1 = new Set(); 17842 var didWarnOnInvalidCallback = new Set(); 17843 17844 warnOnInvalidCallback = function (callback, callerName) { 17845 if (callback === null || typeof callback === 'function') { 17846 return; 17847 } 17848 17849 var key = callerName + '_' + callback; 17850 17851 if (!didWarnOnInvalidCallback.has(key)) { 17852 didWarnOnInvalidCallback.add(key); 17853 17854 error('%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback); 17855 } 17856 }; 17857 17858 warnOnUndefinedDerivedState = function (type, partialState) { 17859 if (partialState === undefined) { 17860 var componentName = getComponentNameFromType(type) || 'Component'; 17861 17862 if (!didWarnAboutUndefinedDerivedState.has(componentName)) { 17863 didWarnAboutUndefinedDerivedState.add(componentName); 17864 17865 error('%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. ' + 'You have returned undefined.', componentName); 17866 } 17867 } 17868 }; // This is so gross but it's at least non-critical and can be removed if 17869 // it causes problems. This is meant to give a nicer error message for 17870 // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component, 17871 // ...)) which otherwise throws a "_processChildContext is not a function" 17872 // exception. 17873 17874 17875 Object.defineProperty(fakeInternalInstance, '_processChildContext', { 17876 enumerable: false, 17877 value: function () { 17878 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).'); 17879 } 17880 }); 17881 Object.freeze(fakeInternalInstance); 17882 } 17883 17884 function applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, nextProps) { 17885 var prevState = workInProgress.memoizedState; 17886 var partialState = getDerivedStateFromProps(nextProps, prevState); 17887 17888 { 17889 if ( workInProgress.mode & StrictLegacyMode) { 17890 setIsStrictModeForDevtools(true); 17891 17892 try { 17893 // Invoke the function an extra time to help detect side-effects. 17894 partialState = getDerivedStateFromProps(nextProps, prevState); 17895 } finally { 17896 setIsStrictModeForDevtools(false); 17897 } 17898 } 17899 17900 warnOnUndefinedDerivedState(ctor, partialState); 17901 } // Merge the partial state and the previous state. 17902 17903 17904 var memoizedState = partialState === null || partialState === undefined ? prevState : assign({}, prevState, partialState); 17905 workInProgress.memoizedState = memoizedState; // Once the update queue is empty, persist the derived state onto the 17906 // base state. 17907 17908 if (workInProgress.lanes === NoLanes) { 17909 // Queue is always non-null for classes 17910 var updateQueue = workInProgress.updateQueue; 17911 updateQueue.baseState = memoizedState; 17912 } 17913 } 17914 17915 var classComponentUpdater = { 17916 isMounted: isMounted, 17917 enqueueSetState: function (inst, payload, callback) { 17918 var fiber = get(inst); 17919 var eventTime = requestEventTime(); 17920 var lane = requestUpdateLane(fiber); 17921 var update = createUpdate(eventTime, lane); 17922 update.payload = payload; 17923 17924 if (callback !== undefined && callback !== null) { 17925 { 17926 warnOnInvalidCallback(callback, 'setState'); 17927 } 17928 17929 update.callback = callback; 17930 } 17931 17932 var root = enqueueUpdate(fiber, update, lane); 17933 17934 if (root !== null) { 17935 scheduleUpdateOnFiber(root, fiber, lane, eventTime); 17936 entangleTransitions(root, fiber, lane); 17937 } 17938 17939 { 17940 markStateUpdateScheduled(fiber, lane); 17941 } 17942 }, 17943 enqueueReplaceState: function (inst, payload, callback) { 17944 var fiber = get(inst); 17945 var eventTime = requestEventTime(); 17946 var lane = requestUpdateLane(fiber); 17947 var update = createUpdate(eventTime, lane); 17948 update.tag = ReplaceState; 17949 update.payload = payload; 17950 17951 if (callback !== undefined && callback !== null) { 17952 { 17953 warnOnInvalidCallback(callback, 'replaceState'); 17954 } 17955 17956 update.callback = callback; 17957 } 17958 17959 var root = enqueueUpdate(fiber, update, lane); 17960 17961 if (root !== null) { 17962 scheduleUpdateOnFiber(root, fiber, lane, eventTime); 17963 entangleTransitions(root, fiber, lane); 17964 } 17965 17966 { 17967 markStateUpdateScheduled(fiber, lane); 17968 } 17969 }, 17970 enqueueForceUpdate: function (inst, callback) { 17971 var fiber = get(inst); 17972 var eventTime = requestEventTime(); 17973 var lane = requestUpdateLane(fiber); 17974 var update = createUpdate(eventTime, lane); 17975 update.tag = ForceUpdate; 17976 17977 if (callback !== undefined && callback !== null) { 17978 { 17979 warnOnInvalidCallback(callback, 'forceUpdate'); 17980 } 17981 17982 update.callback = callback; 17983 } 17984 17985 var root = enqueueUpdate(fiber, update, lane); 17986 17987 if (root !== null) { 17988 scheduleUpdateOnFiber(root, fiber, lane, eventTime); 17989 entangleTransitions(root, fiber, lane); 17990 } 17991 17992 { 17993 markForceUpdateScheduled(fiber, lane); 17994 } 17995 } 17996 }; 17997 17998 function checkShouldComponentUpdate(workInProgress, ctor, oldProps, newProps, oldState, newState, nextContext) { 17999 var instance = workInProgress.stateNode; 18000 18001 if (typeof instance.shouldComponentUpdate === 'function') { 18002 var shouldUpdate = instance.shouldComponentUpdate(newProps, newState, nextContext); 18003 18004 { 18005 if ( workInProgress.mode & StrictLegacyMode) { 18006 setIsStrictModeForDevtools(true); 18007 18008 try { 18009 // Invoke the function an extra time to help detect side-effects. 18010 shouldUpdate = instance.shouldComponentUpdate(newProps, newState, nextContext); 18011 } finally { 18012 setIsStrictModeForDevtools(false); 18013 } 18014 } 18015 18016 if (shouldUpdate === undefined) { 18017 error('%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', getComponentNameFromType(ctor) || 'Component'); 18018 } 18019 } 18020 18021 return shouldUpdate; 18022 } 18023 18024 if (ctor.prototype && ctor.prototype.isPureReactComponent) { 18025 return !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState); 18026 } 18027 18028 return true; 18029 } 18030 18031 function checkClassInstance(workInProgress, ctor, newProps) { 18032 var instance = workInProgress.stateNode; 18033 18034 { 18035 var name = getComponentNameFromType(ctor) || 'Component'; 18036 var renderPresent = instance.render; 18037 18038 if (!renderPresent) { 18039 if (ctor.prototype && typeof ctor.prototype.render === 'function') { 18040 error('%s(...): No `render` method found on the returned component ' + 'instance: did you accidentally return an object from the constructor?', name); 18041 } else { 18042 error('%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', name); 18043 } 18044 } 18045 18046 if (instance.getInitialState && !instance.getInitialState.isReactClassApproved && !instance.state) { 18047 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); 18048 } 18049 18050 if (instance.getDefaultProps && !instance.getDefaultProps.isReactClassApproved) { 18051 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); 18052 } 18053 18054 if (instance.propTypes) { 18055 error('propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', name); 18056 } 18057 18058 if (instance.contextType) { 18059 error('contextType was defined as an instance property on %s. Use a static ' + 'property to define contextType instead.', name); 18060 } 18061 18062 { 18063 if (ctor.childContextTypes && !didWarnAboutLegacyContext$1.has(ctor) && // Strict Mode has its own warning for legacy context, so we can skip 18064 // this one. 18065 (workInProgress.mode & StrictLegacyMode) === NoMode) { 18066 didWarnAboutLegacyContext$1.add(ctor); 18067 18068 error('%s uses the legacy childContextTypes API which is no longer ' + 'supported and will be removed in the next major release. Use ' + 'React.createContext() instead\n\n.' + 'Learn more about this warning here: https://reactjs.org/link/legacy-context', name); 18069 } 18070 18071 if (ctor.contextTypes && !didWarnAboutLegacyContext$1.has(ctor) && // Strict Mode has its own warning for legacy context, so we can skip 18072 // this one. 18073 (workInProgress.mode & StrictLegacyMode) === NoMode) { 18074 didWarnAboutLegacyContext$1.add(ctor); 18075 18076 error('%s uses the legacy contextTypes API which is no longer supported ' + 'and will be removed in the next major release. Use ' + 'React.createContext() with static contextType instead.\n\n' + 'Learn more about this warning here: https://reactjs.org/link/legacy-context', name); 18077 } 18078 18079 if (instance.contextTypes) { 18080 error('contextTypes was defined as an instance property on %s. Use a static ' + 'property to define contextTypes instead.', name); 18081 } 18082 18083 if (ctor.contextType && ctor.contextTypes && !didWarnAboutContextTypeAndContextTypes.has(ctor)) { 18084 didWarnAboutContextTypeAndContextTypes.add(ctor); 18085 18086 error('%s declares both contextTypes and contextType static properties. ' + 'The legacy contextTypes property will be ignored.', name); 18087 } 18088 } 18089 18090 if (typeof instance.componentShouldUpdate === 'function') { 18091 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); 18092 } 18093 18094 if (ctor.prototype && ctor.prototype.isPureReactComponent && typeof instance.shouldComponentUpdate !== 'undefined') { 18095 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'); 18096 } 18097 18098 if (typeof instance.componentDidUnmount === 'function') { 18099 error('%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', name); 18100 } 18101 18102 if (typeof instance.componentDidReceiveProps === 'function') { 18103 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); 18104 } 18105 18106 if (typeof instance.componentWillRecieveProps === 'function') { 18107 error('%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', name); 18108 } 18109 18110 if (typeof instance.UNSAFE_componentWillRecieveProps === 'function') { 18111 error('%s has a method called ' + 'UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?', name); 18112 } 18113 18114 var hasMutatedProps = instance.props !== newProps; 18115 18116 if (instance.props !== undefined && hasMutatedProps) { 18117 error('%s(...): When calling super() in `%s`, make sure to pass ' + "up the same props that your component's constructor was passed.", name, name); 18118 } 18119 18120 if (instance.defaultProps) { 18121 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); 18122 } 18123 18124 if (typeof instance.getSnapshotBeforeUpdate === 'function' && typeof instance.componentDidUpdate !== 'function' && !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor)) { 18125 didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor); 18126 18127 error('%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). ' + 'This component defines getSnapshotBeforeUpdate() only.', getComponentNameFromType(ctor)); 18128 } 18129 18130 if (typeof instance.getDerivedStateFromProps === 'function') { 18131 error('%s: getDerivedStateFromProps() is defined as an instance method ' + 'and will be ignored. Instead, declare it as a static method.', name); 18132 } 18133 18134 if (typeof instance.getDerivedStateFromError === 'function') { 18135 error('%s: getDerivedStateFromError() is defined as an instance method ' + 'and will be ignored. Instead, declare it as a static method.', name); 18136 } 18137 18138 if (typeof ctor.getSnapshotBeforeUpdate === 'function') { 18139 error('%s: getSnapshotBeforeUpdate() is defined as a static method ' + 'and will be ignored. Instead, declare it as an instance method.', name); 18140 } 18141 18142 var _state = instance.state; 18143 18144 if (_state && (typeof _state !== 'object' || isArray(_state))) { 18145 error('%s.state: must be set to an object or null', name); 18146 } 18147 18148 if (typeof instance.getChildContext === 'function' && typeof ctor.childContextTypes !== 'object') { 18149 error('%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', name); 18150 } 18151 } 18152 } 18153 18154 function adoptClassInstance(workInProgress, instance) { 18155 instance.updater = classComponentUpdater; 18156 workInProgress.stateNode = instance; // The instance needs access to the fiber so that it can schedule updates 18157 18158 set(instance, workInProgress); 18159 18160 { 18161 instance._reactInternalInstance = fakeInternalInstance; 18162 } 18163 } 18164 18165 function constructClassInstance(workInProgress, ctor, props) { 18166 var isLegacyContextConsumer = false; 18167 var unmaskedContext = emptyContextObject; 18168 var context = emptyContextObject; 18169 var contextType = ctor.contextType; 18170 18171 { 18172 if ('contextType' in ctor) { 18173 var isValid = // Allow null for conditional declaration 18174 contextType === null || contextType !== undefined && contextType.$$typeof === REACT_CONTEXT_TYPE && contextType._context === undefined; // Not a <Context.Consumer> 18175 18176 if (!isValid && !didWarnAboutInvalidateContextType.has(ctor)) { 18177 didWarnAboutInvalidateContextType.add(ctor); 18178 var addendum = ''; 18179 18180 if (contextType === undefined) { 18181 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.'; 18182 } else if (typeof contextType !== 'object') { 18183 addendum = ' However, it is set to a ' + typeof contextType + '.'; 18184 } else if (contextType.$$typeof === REACT_PROVIDER_TYPE) { 18185 addendum = ' Did you accidentally pass the Context.Provider instead?'; 18186 } else if (contextType._context !== undefined) { 18187 // <Context.Consumer> 18188 addendum = ' Did you accidentally pass the Context.Consumer instead?'; 18189 } else { 18190 addendum = ' However, it is set to an object with keys {' + Object.keys(contextType).join(', ') + '}.'; 18191 } 18192 18193 error('%s defines an invalid contextType. ' + 'contextType should point to the Context object returned by React.createContext().%s', getComponentNameFromType(ctor) || 'Component', addendum); 18194 } 18195 } 18196 } 18197 18198 if (typeof contextType === 'object' && contextType !== null) { 18199 context = readContext(contextType); 18200 } else { 18201 unmaskedContext = getUnmaskedContext(workInProgress, ctor, true); 18202 var contextTypes = ctor.contextTypes; 18203 isLegacyContextConsumer = contextTypes !== null && contextTypes !== undefined; 18204 context = isLegacyContextConsumer ? getMaskedContext(workInProgress, unmaskedContext) : emptyContextObject; 18205 } 18206 18207 var instance = new ctor(props, context); // Instantiate twice to help detect side-effects. 18208 18209 { 18210 if ( workInProgress.mode & StrictLegacyMode) { 18211 setIsStrictModeForDevtools(true); 18212 18213 try { 18214 instance = new ctor(props, context); // eslint-disable-line no-new 18215 } finally { 18216 setIsStrictModeForDevtools(false); 18217 } 18218 } 18219 } 18220 18221 var state = workInProgress.memoizedState = instance.state !== null && instance.state !== undefined ? instance.state : null; 18222 adoptClassInstance(workInProgress, instance); 18223 18224 { 18225 if (typeof ctor.getDerivedStateFromProps === 'function' && state === null) { 18226 var componentName = getComponentNameFromType(ctor) || 'Component'; 18227 18228 if (!didWarnAboutUninitializedState.has(componentName)) { 18229 didWarnAboutUninitializedState.add(componentName); 18230 18231 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); 18232 } 18233 } // If new component APIs are defined, "unsafe" lifecycles won't be called. 18234 // Warn about these lifecycles if they are present. 18235 // Don't warn about react-lifecycles-compat polyfilled methods though. 18236 18237 18238 if (typeof ctor.getDerivedStateFromProps === 'function' || typeof instance.getSnapshotBeforeUpdate === 'function') { 18239 var foundWillMountName = null; 18240 var foundWillReceivePropsName = null; 18241 var foundWillUpdateName = null; 18242 18243 if (typeof instance.componentWillMount === 'function' && instance.componentWillMount.__suppressDeprecationWarning !== true) { 18244 foundWillMountName = 'componentWillMount'; 18245 } else if (typeof instance.UNSAFE_componentWillMount === 'function') { 18246 foundWillMountName = 'UNSAFE_componentWillMount'; 18247 } 18248 18249 if (typeof instance.componentWillReceiveProps === 'function' && instance.componentWillReceiveProps.__suppressDeprecationWarning !== true) { 18250 foundWillReceivePropsName = 'componentWillReceiveProps'; 18251 } else if (typeof instance.UNSAFE_componentWillReceiveProps === 'function') { 18252 foundWillReceivePropsName = 'UNSAFE_componentWillReceiveProps'; 18253 } 18254 18255 if (typeof instance.componentWillUpdate === 'function' && instance.componentWillUpdate.__suppressDeprecationWarning !== true) { 18256 foundWillUpdateName = 'componentWillUpdate'; 18257 } else if (typeof instance.UNSAFE_componentWillUpdate === 'function') { 18258 foundWillUpdateName = 'UNSAFE_componentWillUpdate'; 18259 } 18260 18261 if (foundWillMountName !== null || foundWillReceivePropsName !== null || foundWillUpdateName !== null) { 18262 var _componentName = getComponentNameFromType(ctor) || 'Component'; 18263 18264 var newApiName = typeof ctor.getDerivedStateFromProps === 'function' ? 'getDerivedStateFromProps()' : 'getSnapshotBeforeUpdate()'; 18265 18266 if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName)) { 18267 didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName); 18268 18269 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 : ''); 18270 } 18271 } 18272 } 18273 } // Cache unmasked context so we can avoid recreating masked context unless necessary. 18274 // ReactFiberContext usually updates this cache but can't for newly-created instances. 18275 18276 18277 if (isLegacyContextConsumer) { 18278 cacheContext(workInProgress, unmaskedContext, context); 18279 } 18280 18281 return instance; 18282 } 18283 18284 function callComponentWillMount(workInProgress, instance) { 18285 var oldState = instance.state; 18286 18287 if (typeof instance.componentWillMount === 'function') { 18288 instance.componentWillMount(); 18289 } 18290 18291 if (typeof instance.UNSAFE_componentWillMount === 'function') { 18292 instance.UNSAFE_componentWillMount(); 18293 } 18294 18295 if (oldState !== instance.state) { 18296 { 18297 error('%s.componentWillMount(): Assigning directly to this.state is ' + "deprecated (except inside a component's " + 'constructor). Use setState instead.', getComponentNameFromFiber(workInProgress) || 'Component'); 18298 } 18299 18300 classComponentUpdater.enqueueReplaceState(instance, instance.state, null); 18301 } 18302 } 18303 18304 function callComponentWillReceiveProps(workInProgress, instance, newProps, nextContext) { 18305 var oldState = instance.state; 18306 18307 if (typeof instance.componentWillReceiveProps === 'function') { 18308 instance.componentWillReceiveProps(newProps, nextContext); 18309 } 18310 18311 if (typeof instance.UNSAFE_componentWillReceiveProps === 'function') { 18312 instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); 18313 } 18314 18315 if (instance.state !== oldState) { 18316 { 18317 var componentName = getComponentNameFromFiber(workInProgress) || 'Component'; 18318 18319 if (!didWarnAboutStateAssignmentForComponent.has(componentName)) { 18320 didWarnAboutStateAssignmentForComponent.add(componentName); 18321 18322 error('%s.componentWillReceiveProps(): Assigning directly to ' + "this.state is deprecated (except inside a component's " + 'constructor). Use setState instead.', componentName); 18323 } 18324 } 18325 18326 classComponentUpdater.enqueueReplaceState(instance, instance.state, null); 18327 } 18328 } // Invokes the mount life-cycles on a previously never rendered instance. 18329 18330 18331 function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { 18332 { 18333 checkClassInstance(workInProgress, ctor, newProps); 18334 } 18335 18336 var instance = workInProgress.stateNode; 18337 instance.props = newProps; 18338 instance.state = workInProgress.memoizedState; 18339 instance.refs = {}; 18340 initializeUpdateQueue(workInProgress); 18341 var contextType = ctor.contextType; 18342 18343 if (typeof contextType === 'object' && contextType !== null) { 18344 instance.context = readContext(contextType); 18345 } else { 18346 var unmaskedContext = getUnmaskedContext(workInProgress, ctor, true); 18347 instance.context = getMaskedContext(workInProgress, unmaskedContext); 18348 } 18349 18350 { 18351 if (instance.state === newProps) { 18352 var componentName = getComponentNameFromType(ctor) || 'Component'; 18353 18354 if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) { 18355 didWarnAboutDirectlyAssigningPropsToState.add(componentName); 18356 18357 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); 18358 } 18359 } 18360 18361 if (workInProgress.mode & StrictLegacyMode) { 18362 ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, instance); 18363 } 18364 18365 { 18366 ReactStrictModeWarnings.recordUnsafeLifecycleWarnings(workInProgress, instance); 18367 } 18368 } 18369 18370 instance.state = workInProgress.memoizedState; 18371 var getDerivedStateFromProps = ctor.getDerivedStateFromProps; 18372 18373 if (typeof getDerivedStateFromProps === 'function') { 18374 applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, newProps); 18375 instance.state = workInProgress.memoizedState; 18376 } // In order to support react-lifecycles-compat polyfilled components, 18377 // Unsafe lifecycles should not be invoked for components using the new APIs. 18378 18379 18380 if (typeof ctor.getDerivedStateFromProps !== 'function' && typeof instance.getSnapshotBeforeUpdate !== 'function' && (typeof instance.UNSAFE_componentWillMount === 'function' || typeof instance.componentWillMount === 'function')) { 18381 callComponentWillMount(workInProgress, instance); // If we had additional state updates during this life-cycle, let's 18382 // process them now. 18383 18384 processUpdateQueue(workInProgress, newProps, instance, renderLanes); 18385 instance.state = workInProgress.memoizedState; 18386 } 18387 18388 if (typeof instance.componentDidMount === 'function') { 18389 var fiberFlags = Update; 18390 18391 { 18392 fiberFlags |= LayoutStatic; 18393 } 18394 18395 if ( (workInProgress.mode & StrictEffectsMode) !== NoMode) { 18396 fiberFlags |= MountLayoutDev; 18397 } 18398 18399 workInProgress.flags |= fiberFlags; 18400 } 18401 } 18402 18403 function resumeMountClassInstance(workInProgress, ctor, newProps, renderLanes) { 18404 var instance = workInProgress.stateNode; 18405 var oldProps = workInProgress.memoizedProps; 18406 instance.props = oldProps; 18407 var oldContext = instance.context; 18408 var contextType = ctor.contextType; 18409 var nextContext = emptyContextObject; 18410 18411 if (typeof contextType === 'object' && contextType !== null) { 18412 nextContext = readContext(contextType); 18413 } else { 18414 var nextLegacyUnmaskedContext = getUnmaskedContext(workInProgress, ctor, true); 18415 nextContext = getMaskedContext(workInProgress, nextLegacyUnmaskedContext); 18416 } 18417 18418 var getDerivedStateFromProps = ctor.getDerivedStateFromProps; 18419 var hasNewLifecycles = typeof getDerivedStateFromProps === 'function' || typeof instance.getSnapshotBeforeUpdate === 'function'; // Note: During these life-cycles, instance.props/instance.state are what 18420 // ever the previously attempted to render - not the "current". However, 18421 // during componentDidUpdate we pass the "current" props. 18422 // In order to support react-lifecycles-compat polyfilled components, 18423 // Unsafe lifecycles should not be invoked for components using the new APIs. 18424 18425 if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillReceiveProps === 'function' || typeof instance.componentWillReceiveProps === 'function')) { 18426 if (oldProps !== newProps || oldContext !== nextContext) { 18427 callComponentWillReceiveProps(workInProgress, instance, newProps, nextContext); 18428 } 18429 } 18430 18431 resetHasForceUpdateBeforeProcessing(); 18432 var oldState = workInProgress.memoizedState; 18433 var newState = instance.state = oldState; 18434 processUpdateQueue(workInProgress, newProps, instance, renderLanes); 18435 newState = workInProgress.memoizedState; 18436 18437 if (oldProps === newProps && oldState === newState && !hasContextChanged() && !checkHasForceUpdateAfterProcessing()) { 18438 // If an update was already in progress, we should schedule an Update 18439 // effect even though we're bailing out, so that cWU/cDU are called. 18440 if (typeof instance.componentDidMount === 'function') { 18441 var fiberFlags = Update; 18442 18443 { 18444 fiberFlags |= LayoutStatic; 18445 } 18446 18447 if ( (workInProgress.mode & StrictEffectsMode) !== NoMode) { 18448 fiberFlags |= MountLayoutDev; 18449 } 18450 18451 workInProgress.flags |= fiberFlags; 18452 } 18453 18454 return false; 18455 } 18456 18457 if (typeof getDerivedStateFromProps === 'function') { 18458 applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, newProps); 18459 newState = workInProgress.memoizedState; 18460 } 18461 18462 var shouldUpdate = checkHasForceUpdateAfterProcessing() || checkShouldComponentUpdate(workInProgress, ctor, oldProps, newProps, oldState, newState, nextContext); 18463 18464 if (shouldUpdate) { 18465 // In order to support react-lifecycles-compat polyfilled components, 18466 // Unsafe lifecycles should not be invoked for components using the new APIs. 18467 if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillMount === 'function' || typeof instance.componentWillMount === 'function')) { 18468 if (typeof instance.componentWillMount === 'function') { 18469 instance.componentWillMount(); 18470 } 18471 18472 if (typeof instance.UNSAFE_componentWillMount === 'function') { 18473 instance.UNSAFE_componentWillMount(); 18474 } 18475 } 18476 18477 if (typeof instance.componentDidMount === 'function') { 18478 var _fiberFlags = Update; 18479 18480 { 18481 _fiberFlags |= LayoutStatic; 18482 } 18483 18484 if ( (workInProgress.mode & StrictEffectsMode) !== NoMode) { 18485 _fiberFlags |= MountLayoutDev; 18486 } 18487 18488 workInProgress.flags |= _fiberFlags; 18489 } 18490 } else { 18491 // If an update was already in progress, we should schedule an Update 18492 // effect even though we're bailing out, so that cWU/cDU are called. 18493 if (typeof instance.componentDidMount === 'function') { 18494 var _fiberFlags2 = Update; 18495 18496 { 18497 _fiberFlags2 |= LayoutStatic; 18498 } 18499 18500 if ( (workInProgress.mode & StrictEffectsMode) !== NoMode) { 18501 _fiberFlags2 |= MountLayoutDev; 18502 } 18503 18504 workInProgress.flags |= _fiberFlags2; 18505 } // If shouldComponentUpdate returned false, we should still update the 18506 // memoized state to indicate that this work can be reused. 18507 18508 18509 workInProgress.memoizedProps = newProps; 18510 workInProgress.memoizedState = newState; 18511 } // Update the existing instance's state, props, and context pointers even 18512 // if shouldComponentUpdate returns false. 18513 18514 18515 instance.props = newProps; 18516 instance.state = newState; 18517 instance.context = nextContext; 18518 return shouldUpdate; 18519 } // Invokes the update life-cycles and returns false if it shouldn't rerender. 18520 18521 18522 function updateClassInstance(current, workInProgress, ctor, newProps, renderLanes) { 18523 var instance = workInProgress.stateNode; 18524 cloneUpdateQueue(current, workInProgress); 18525 var unresolvedOldProps = workInProgress.memoizedProps; 18526 var oldProps = workInProgress.type === workInProgress.elementType ? unresolvedOldProps : resolveDefaultProps(workInProgress.type, unresolvedOldProps); 18527 instance.props = oldProps; 18528 var unresolvedNewProps = workInProgress.pendingProps; 18529 var oldContext = instance.context; 18530 var contextType = ctor.contextType; 18531 var nextContext = emptyContextObject; 18532 18533 if (typeof contextType === 'object' && contextType !== null) { 18534 nextContext = readContext(contextType); 18535 } else { 18536 var nextUnmaskedContext = getUnmaskedContext(workInProgress, ctor, true); 18537 nextContext = getMaskedContext(workInProgress, nextUnmaskedContext); 18538 } 18539 18540 var getDerivedStateFromProps = ctor.getDerivedStateFromProps; 18541 var hasNewLifecycles = typeof getDerivedStateFromProps === 'function' || typeof instance.getSnapshotBeforeUpdate === 'function'; // Note: During these life-cycles, instance.props/instance.state are what 18542 // ever the previously attempted to render - not the "current". However, 18543 // during componentDidUpdate we pass the "current" props. 18544 // In order to support react-lifecycles-compat polyfilled components, 18545 // Unsafe lifecycles should not be invoked for components using the new APIs. 18546 18547 if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillReceiveProps === 'function' || typeof instance.componentWillReceiveProps === 'function')) { 18548 if (unresolvedOldProps !== unresolvedNewProps || oldContext !== nextContext) { 18549 callComponentWillReceiveProps(workInProgress, instance, newProps, nextContext); 18550 } 18551 } 18552 18553 resetHasForceUpdateBeforeProcessing(); 18554 var oldState = workInProgress.memoizedState; 18555 var newState = instance.state = oldState; 18556 processUpdateQueue(workInProgress, newProps, instance, renderLanes); 18557 newState = workInProgress.memoizedState; 18558 18559 if (unresolvedOldProps === unresolvedNewProps && oldState === newState && !hasContextChanged() && !checkHasForceUpdateAfterProcessing() && !(enableLazyContextPropagation )) { 18560 // If an update was already in progress, we should schedule an Update 18561 // effect even though we're bailing out, so that cWU/cDU are called. 18562 if (typeof instance.componentDidUpdate === 'function') { 18563 if (unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState) { 18564 workInProgress.flags |= Update; 18565 } 18566 } 18567 18568 if (typeof instance.getSnapshotBeforeUpdate === 'function') { 18569 if (unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState) { 18570 workInProgress.flags |= Snapshot; 18571 } 18572 } 18573 18574 return false; 18575 } 18576 18577 if (typeof getDerivedStateFromProps === 'function') { 18578 applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, newProps); 18579 newState = workInProgress.memoizedState; 18580 } 18581 18582 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, 18583 // both before and after `shouldComponentUpdate` has been called. Not ideal, 18584 // but I'm loath to refactor this function. This only happens for memoized 18585 // components so it's not that common. 18586 enableLazyContextPropagation ; 18587 18588 if (shouldUpdate) { 18589 // In order to support react-lifecycles-compat polyfilled components, 18590 // Unsafe lifecycles should not be invoked for components using the new APIs. 18591 if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillUpdate === 'function' || typeof instance.componentWillUpdate === 'function')) { 18592 if (typeof instance.componentWillUpdate === 'function') { 18593 instance.componentWillUpdate(newProps, newState, nextContext); 18594 } 18595 18596 if (typeof instance.UNSAFE_componentWillUpdate === 'function') { 18597 instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext); 18598 } 18599 } 18600 18601 if (typeof instance.componentDidUpdate === 'function') { 18602 workInProgress.flags |= Update; 18603 } 18604 18605 if (typeof instance.getSnapshotBeforeUpdate === 'function') { 18606 workInProgress.flags |= Snapshot; 18607 } 18608 } else { 18609 // If an update was already in progress, we should schedule an Update 18610 // effect even though we're bailing out, so that cWU/cDU are called. 18611 if (typeof instance.componentDidUpdate === 'function') { 18612 if (unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState) { 18613 workInProgress.flags |= Update; 18614 } 18615 } 18616 18617 if (typeof instance.getSnapshotBeforeUpdate === 'function') { 18618 if (unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState) { 18619 workInProgress.flags |= Snapshot; 18620 } 18621 } // If shouldComponentUpdate returned false, we should still update the 18622 // memoized props/state to indicate that this work can be reused. 18623 18624 18625 workInProgress.memoizedProps = newProps; 18626 workInProgress.memoizedState = newState; 18627 } // Update the existing instance's state, props, and context pointers even 18628 // if shouldComponentUpdate returns false. 18629 18630 18631 instance.props = newProps; 18632 instance.state = newState; 18633 instance.context = nextContext; 18634 return shouldUpdate; 18635 } 18636 18637 function createCapturedValueAtFiber(value, source) { 18638 // If the value is an error, call this function immediately after it is thrown 18639 // so the stack is accurate. 18640 return { 18641 value: value, 18642 source: source, 18643 stack: getStackByFiberInDevAndProd(source), 18644 digest: null 18645 }; 18646 } 18647 function createCapturedValue(value, digest, stack) { 18648 return { 18649 value: value, 18650 source: null, 18651 stack: stack != null ? stack : null, 18652 digest: digest != null ? digest : null 18653 }; 18654 } 18655 18656 // This module is forked in different environments. 18657 // By default, return `true` to log errors to the console. 18658 // Forks can return `false` if this isn't desirable. 18659 function showErrorDialog(boundary, errorInfo) { 18660 return true; 18661 } 18662 18663 function logCapturedError(boundary, errorInfo) { 18664 try { 18665 var logError = showErrorDialog(boundary, errorInfo); // Allow injected showErrorDialog() to prevent default console.error logging. 18666 // This enables renderers like ReactNative to better manage redbox behavior. 18667 18668 if (logError === false) { 18669 return; 18670 } 18671 18672 var error = errorInfo.value; 18673 18674 if (true) { 18675 var source = errorInfo.source; 18676 var stack = errorInfo.stack; 18677 var componentStack = stack !== null ? stack : ''; // Browsers support silencing uncaught errors by calling 18678 // `preventDefault()` in window `error` handler. 18679 // We record this information as an expando on the error. 18680 18681 if (error != null && error._suppressLogging) { 18682 if (boundary.tag === ClassComponent) { 18683 // The error is recoverable and was silenced. 18684 // Ignore it and don't print the stack addendum. 18685 // This is handy for testing error boundaries without noise. 18686 return; 18687 } // The error is fatal. Since the silencing might have 18688 // been accidental, we'll surface it anyway. 18689 // However, the browser would have silenced the original error 18690 // so we'll print it first, and then print the stack addendum. 18691 18692 18693 console['error'](error); // Don't transform to our wrapper 18694 // For a more detailed description of this block, see: 18695 // https://github.com/facebook/react/pull/13384 18696 } 18697 18698 var componentName = source ? getComponentNameFromFiber(source) : null; 18699 var componentNameMessage = componentName ? "The above error occurred in the <" + componentName + "> component:" : 'The above error occurred in one of your React components:'; 18700 var errorBoundaryMessage; 18701 18702 if (boundary.tag === HostRoot) { 18703 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.'; 18704 } else { 18705 var errorBoundaryName = getComponentNameFromFiber(boundary) || 'Anonymous'; 18706 errorBoundaryMessage = "React will try to recreate this component tree from scratch " + ("using the error boundary you provided, " + errorBoundaryName + "."); 18707 } 18708 18709 var combinedMessage = componentNameMessage + "\n" + componentStack + "\n\n" + ("" + errorBoundaryMessage); // In development, we provide our own message with just the component stack. 18710 // We don't include the original error message and JS stack because the browser 18711 // has already printed it. Even if the application swallows the error, it is still 18712 // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils. 18713 18714 console['error'](combinedMessage); // Don't transform to our wrapper 18715 } else { 18716 // In production, we print the error directly. 18717 // This will include the message, the JS stack, and anything the browser wants to show. 18718 // We pass the error object instead of custom message so that the browser displays the error natively. 18719 console['error'](error); // Don't transform to our wrapper 18720 } 18721 } catch (e) { 18722 // This method must not throw, or React internal state will get messed up. 18723 // If console.error is overridden, or logCapturedError() shows a dialog that throws, 18724 // we want to report this error outside of the normal stack as a last resort. 18725 // https://github.com/facebook/react/issues/13188 18726 setTimeout(function () { 18727 throw e; 18728 }); 18729 } 18730 } 18731 18732 var PossiblyWeakMap$1 = typeof WeakMap === 'function' ? WeakMap : Map; 18733 18734 function createRootErrorUpdate(fiber, errorInfo, lane) { 18735 var update = createUpdate(NoTimestamp, lane); // Unmount the root by rendering null. 18736 18737 update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property 18738 // being called "element". 18739 18740 update.payload = { 18741 element: null 18742 }; 18743 var error = errorInfo.value; 18744 18745 update.callback = function () { 18746 onUncaughtError(error); 18747 logCapturedError(fiber, errorInfo); 18748 }; 18749 18750 return update; 18751 } 18752 18753 function createClassErrorUpdate(fiber, errorInfo, lane) { 18754 var update = createUpdate(NoTimestamp, lane); 18755 update.tag = CaptureUpdate; 18756 var getDerivedStateFromError = fiber.type.getDerivedStateFromError; 18757 18758 if (typeof getDerivedStateFromError === 'function') { 18759 var error$1 = errorInfo.value; 18760 18761 update.payload = function () { 18762 return getDerivedStateFromError(error$1); 18763 }; 18764 18765 update.callback = function () { 18766 { 18767 markFailedErrorBoundaryForHotReloading(fiber); 18768 } 18769 18770 logCapturedError(fiber, errorInfo); 18771 }; 18772 } 18773 18774 var inst = fiber.stateNode; 18775 18776 if (inst !== null && typeof inst.componentDidCatch === 'function') { 18777 update.callback = function callback() { 18778 { 18779 markFailedErrorBoundaryForHotReloading(fiber); 18780 } 18781 18782 logCapturedError(fiber, errorInfo); 18783 18784 if (typeof getDerivedStateFromError !== 'function') { 18785 // To preserve the preexisting retry behavior of error boundaries, 18786 // we keep track of which ones already failed during this batch. 18787 // This gets reset before we yield back to the browser. 18788 // TODO: Warn in strict mode if getDerivedStateFromError is 18789 // not defined. 18790 markLegacyErrorBoundaryAsFailed(this); 18791 } 18792 18793 var error$1 = errorInfo.value; 18794 var stack = errorInfo.stack; 18795 this.componentDidCatch(error$1, { 18796 componentStack: stack !== null ? stack : '' 18797 }); 18798 18799 { 18800 if (typeof getDerivedStateFromError !== 'function') { 18801 // If componentDidCatch is the only error boundary method defined, 18802 // then it needs to call setState to recover from errors. 18803 // If no state update is scheduled then the boundary will swallow the error. 18804 if (!includesSomeLane(fiber.lanes, SyncLane)) { 18805 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'); 18806 } 18807 } 18808 } 18809 }; 18810 } 18811 18812 return update; 18813 } 18814 18815 function attachPingListener(root, wakeable, lanes) { 18816 // Attach a ping listener 18817 // 18818 // The data might resolve before we have a chance to commit the fallback. Or, 18819 // in the case of a refresh, we'll never commit a fallback. So we need to 18820 // attach a listener now. When it resolves ("pings"), we can decide whether to 18821 // try rendering the tree again. 18822 // 18823 // Only attach a listener if one does not already exist for the lanes 18824 // we're currently rendering (which acts like a "thread ID" here). 18825 // 18826 // We only need to do this in concurrent mode. Legacy Suspense always 18827 // commits fallbacks synchronously, so there are no pings. 18828 var pingCache = root.pingCache; 18829 var threadIDs; 18830 18831 if (pingCache === null) { 18832 pingCache = root.pingCache = new PossiblyWeakMap$1(); 18833 threadIDs = new Set(); 18834 pingCache.set(wakeable, threadIDs); 18835 } else { 18836 threadIDs = pingCache.get(wakeable); 18837 18838 if (threadIDs === undefined) { 18839 threadIDs = new Set(); 18840 pingCache.set(wakeable, threadIDs); 18841 } 18842 } 18843 18844 if (!threadIDs.has(lanes)) { 18845 // Memoize using the thread ID to prevent redundant listeners. 18846 threadIDs.add(lanes); 18847 var ping = pingSuspendedRoot.bind(null, root, wakeable, lanes); 18848 18849 { 18850 if (isDevToolsPresent) { 18851 // If we have pending work still, restore the original updaters 18852 restorePendingUpdaters(root, lanes); 18853 } 18854 } 18855 18856 wakeable.then(ping, ping); 18857 } 18858 } 18859 18860 function attachRetryListener(suspenseBoundary, root, wakeable, lanes) { 18861 // Retry listener 18862 // 18863 // If the fallback does commit, we need to attach a different type of 18864 // listener. This one schedules an update on the Suspense boundary to turn 18865 // the fallback state off. 18866 // 18867 // Stash the wakeable on the boundary fiber so we can access it in the 18868 // commit phase. 18869 // 18870 // When the wakeable resolves, we'll attempt to render the boundary 18871 // again ("retry"). 18872 var wakeables = suspenseBoundary.updateQueue; 18873 18874 if (wakeables === null) { 18875 var updateQueue = new Set(); 18876 updateQueue.add(wakeable); 18877 suspenseBoundary.updateQueue = updateQueue; 18878 } else { 18879 wakeables.add(wakeable); 18880 } 18881 } 18882 18883 function resetSuspendedComponent(sourceFiber, rootRenderLanes) { 18884 // A legacy mode Suspense quirk, only relevant to hook components. 18885 18886 18887 var tag = sourceFiber.tag; 18888 18889 if ((sourceFiber.mode & ConcurrentMode) === NoMode && (tag === FunctionComponent || tag === ForwardRef || tag === SimpleMemoComponent)) { 18890 var currentSource = sourceFiber.alternate; 18891 18892 if (currentSource) { 18893 sourceFiber.updateQueue = currentSource.updateQueue; 18894 sourceFiber.memoizedState = currentSource.memoizedState; 18895 sourceFiber.lanes = currentSource.lanes; 18896 } else { 18897 sourceFiber.updateQueue = null; 18898 sourceFiber.memoizedState = null; 18899 } 18900 } 18901 } 18902 18903 function getNearestSuspenseBoundaryToCapture(returnFiber) { 18904 var node = returnFiber; 18905 18906 do { 18907 if (node.tag === SuspenseComponent && shouldCaptureSuspense(node)) { 18908 return node; 18909 } // This boundary already captured during this render. Continue to the next 18910 // boundary. 18911 18912 18913 node = node.return; 18914 } while (node !== null); 18915 18916 return null; 18917 } 18918 18919 function markSuspenseBoundaryShouldCapture(suspenseBoundary, returnFiber, sourceFiber, root, rootRenderLanes) { 18920 // This marks a Suspense boundary so that when we're unwinding the stack, 18921 // it captures the suspended "exception" and does a second (fallback) pass. 18922 if ((suspenseBoundary.mode & ConcurrentMode) === NoMode) { 18923 // Legacy Mode Suspense 18924 // 18925 // If the boundary is in legacy mode, we should *not* 18926 // suspend the commit. Pretend as if the suspended component rendered 18927 // null and keep rendering. When the Suspense boundary completes, 18928 // we'll do a second pass to render the fallback. 18929 if (suspenseBoundary === returnFiber) { 18930 // Special case where we suspended while reconciling the children of 18931 // a Suspense boundary's inner Offscreen wrapper fiber. This happens 18932 // when a React.lazy component is a direct child of a 18933 // Suspense boundary. 18934 // 18935 // Suspense boundaries are implemented as multiple fibers, but they 18936 // are a single conceptual unit. The legacy mode behavior where we 18937 // pretend the suspended fiber committed as `null` won't work, 18938 // because in this case the "suspended" fiber is the inner 18939 // Offscreen wrapper. 18940 // 18941 // Because the contents of the boundary haven't started rendering 18942 // yet (i.e. nothing in the tree has partially rendered) we can 18943 // switch to the regular, concurrent mode behavior: mark the 18944 // boundary with ShouldCapture and enter the unwind phase. 18945 suspenseBoundary.flags |= ShouldCapture; 18946 } else { 18947 suspenseBoundary.flags |= DidCapture; 18948 sourceFiber.flags |= ForceUpdateForLegacySuspense; // We're going to commit this fiber even though it didn't complete. 18949 // But we shouldn't call any lifecycle methods or callbacks. Remove 18950 // all lifecycle effect tags. 18951 18952 sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete); 18953 18954 if (sourceFiber.tag === ClassComponent) { 18955 var currentSourceFiber = sourceFiber.alternate; 18956 18957 if (currentSourceFiber === null) { 18958 // This is a new mount. Change the tag so it's not mistaken for a 18959 // completed class component. For example, we should not call 18960 // componentWillUnmount if it is deleted. 18961 sourceFiber.tag = IncompleteClassComponent; 18962 } else { 18963 // When we try rendering again, we should not reuse the current fiber, 18964 // since it's known to be in an inconsistent state. Use a force update to 18965 // prevent a bail out. 18966 var update = createUpdate(NoTimestamp, SyncLane); 18967 update.tag = ForceUpdate; 18968 enqueueUpdate(sourceFiber, update, SyncLane); 18969 } 18970 } // The source fiber did not complete. Mark it with Sync priority to 18971 // indicate that it still has pending work. 18972 18973 18974 sourceFiber.lanes = mergeLanes(sourceFiber.lanes, SyncLane); 18975 } 18976 18977 return suspenseBoundary; 18978 } // Confirmed that the boundary is in a concurrent mode tree. Continue 18979 // with the normal suspend path. 18980 // 18981 // After this we'll use a set of heuristics to determine whether this 18982 // render pass will run to completion or restart or "suspend" the commit. 18983 // The actual logic for this is spread out in different places. 18984 // 18985 // This first principle is that if we're going to suspend when we complete 18986 // a root, then we should also restart if we get an update or ping that 18987 // might unsuspend it, and vice versa. The only reason to suspend is 18988 // because you think you might want to restart before committing. However, 18989 // it doesn't make sense to restart only while in the period we're suspended. 18990 // 18991 // Restarting too aggressively is also not good because it starves out any 18992 // intermediate loading state. So we use heuristics to determine when. 18993 // Suspense Heuristics 18994 // 18995 // If nothing threw a Promise or all the same fallbacks are already showing, 18996 // then don't suspend/restart. 18997 // 18998 // If this is an initial render of a new tree of Suspense boundaries and 18999 // those trigger a fallback, then don't suspend/restart. We want to ensure 19000 // that we can show the initial loading state as quickly as possible. 19001 // 19002 // If we hit a "Delayed" case, such as when we'd switch from content back into 19003 // a fallback, then we should always suspend/restart. Transitions apply 19004 // to this case. If none is defined, JND is used instead. 19005 // 19006 // If we're already showing a fallback and it gets "retried", allowing us to show 19007 // another level, but there's still an inner boundary that would show a fallback, 19008 // then we suspend/restart for 500ms since the last time we showed a fallback 19009 // anywhere in the tree. This effectively throttles progressive loading into a 19010 // consistent train of commits. This also gives us an opportunity to restart to 19011 // get to the completed state slightly earlier. 19012 // 19013 // If there's ambiguity due to batching it's resolved in preference of: 19014 // 1) "delayed", 2) "initial render", 3) "retry". 19015 // 19016 // We want to ensure that a "busy" state doesn't get force committed. We want to 19017 // ensure that new initial loading states can commit as soon as possible. 19018 19019 19020 suspenseBoundary.flags |= ShouldCapture; // TODO: I think we can remove this, since we now use `DidCapture` in 19021 // the begin phase to prevent an early bailout. 19022 19023 suspenseBoundary.lanes = rootRenderLanes; 19024 return suspenseBoundary; 19025 } 19026 19027 function throwException(root, returnFiber, sourceFiber, value, rootRenderLanes) { 19028 // The source fiber did not complete. 19029 sourceFiber.flags |= Incomplete; 19030 19031 { 19032 if (isDevToolsPresent) { 19033 // If we have pending work still, restore the original updaters 19034 restorePendingUpdaters(root, rootRenderLanes); 19035 } 19036 } 19037 19038 if (value !== null && typeof value === 'object' && typeof value.then === 'function') { 19039 // This is a wakeable. The component suspended. 19040 var wakeable = value; 19041 resetSuspendedComponent(sourceFiber); 19042 19043 { 19044 if (getIsHydrating() && sourceFiber.mode & ConcurrentMode) { 19045 markDidThrowWhileHydratingDEV(); 19046 } 19047 } 19048 19049 19050 var suspenseBoundary = getNearestSuspenseBoundaryToCapture(returnFiber); 19051 19052 if (suspenseBoundary !== null) { 19053 suspenseBoundary.flags &= ~ForceClientRender; 19054 markSuspenseBoundaryShouldCapture(suspenseBoundary, returnFiber, sourceFiber, root, rootRenderLanes); // We only attach ping listeners in concurrent mode. Legacy Suspense always 19055 // commits fallbacks synchronously, so there are no pings. 19056 19057 if (suspenseBoundary.mode & ConcurrentMode) { 19058 attachPingListener(root, wakeable, rootRenderLanes); 19059 } 19060 19061 attachRetryListener(suspenseBoundary, root, wakeable); 19062 return; 19063 } else { 19064 // No boundary was found. Unless this is a sync update, this is OK. 19065 // We can suspend and wait for more data to arrive. 19066 if (!includesSyncLane(rootRenderLanes)) { 19067 // This is not a sync update. Suspend. Since we're not activating a 19068 // Suspense boundary, this will unwind all the way to the root without 19069 // performing a second pass to render a fallback. (This is arguably how 19070 // refresh transitions should work, too, since we're not going to commit 19071 // the fallbacks anyway.) 19072 // 19073 // This case also applies to initial hydration. 19074 attachPingListener(root, wakeable, rootRenderLanes); 19075 renderDidSuspendDelayIfPossible(); 19076 return; 19077 } // This is a sync/discrete update. We treat this case like an error 19078 // because discrete renders are expected to produce a complete tree 19079 // synchronously to maintain consistency with external state. 19080 19081 19082 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. 19083 // The error will be caught by the nearest suspense boundary. 19084 19085 value = uncaughtSuspenseError; 19086 } 19087 } else { 19088 // This is a regular error, not a Suspense wakeable. 19089 if (getIsHydrating() && sourceFiber.mode & ConcurrentMode) { 19090 markDidThrowWhileHydratingDEV(); 19091 19092 var _suspenseBoundary = getNearestSuspenseBoundaryToCapture(returnFiber); // If the error was thrown during hydration, we may be able to recover by 19093 // discarding the dehydrated content and switching to a client render. 19094 // Instead of surfacing the error, find the nearest Suspense boundary 19095 // and render it again without hydration. 19096 19097 19098 if (_suspenseBoundary !== null) { 19099 if ((_suspenseBoundary.flags & ShouldCapture) === NoFlags) { 19100 // Set a flag to indicate that we should try rendering the normal 19101 // children again, not the fallback. 19102 _suspenseBoundary.flags |= ForceClientRender; 19103 } 19104 19105 markSuspenseBoundaryShouldCapture(_suspenseBoundary, returnFiber, sourceFiber, root, rootRenderLanes); // Even though the user may not be affected by this error, we should 19106 // still log it so it can be fixed. 19107 19108 queueHydrationError(createCapturedValueAtFiber(value, sourceFiber)); 19109 return; 19110 } 19111 } 19112 } 19113 19114 value = createCapturedValueAtFiber(value, sourceFiber); 19115 renderDidError(value); // We didn't find a boundary that could handle this type of exception. Start 19116 // over and traverse parent path again, this time treating the exception 19117 // as an error. 19118 19119 var workInProgress = returnFiber; 19120 19121 do { 19122 switch (workInProgress.tag) { 19123 case HostRoot: 19124 { 19125 var _errorInfo = value; 19126 workInProgress.flags |= ShouldCapture; 19127 var lane = pickArbitraryLane(rootRenderLanes); 19128 workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); 19129 var update = createRootErrorUpdate(workInProgress, _errorInfo, lane); 19130 enqueueCapturedUpdate(workInProgress, update); 19131 return; 19132 } 19133 19134 case ClassComponent: 19135 // Capture and retry 19136 var errorInfo = value; 19137 var ctor = workInProgress.type; 19138 var instance = workInProgress.stateNode; 19139 19140 if ((workInProgress.flags & DidCapture) === NoFlags && (typeof ctor.getDerivedStateFromError === 'function' || instance !== null && typeof instance.componentDidCatch === 'function' && !isAlreadyFailedLegacyErrorBoundary(instance))) { 19141 workInProgress.flags |= ShouldCapture; 19142 19143 var _lane = pickArbitraryLane(rootRenderLanes); 19144 19145 workInProgress.lanes = mergeLanes(workInProgress.lanes, _lane); // Schedule the error boundary to re-render using updated state 19146 19147 var _update = createClassErrorUpdate(workInProgress, errorInfo, _lane); 19148 19149 enqueueCapturedUpdate(workInProgress, _update); 19150 return; 19151 } 19152 19153 break; 19154 } 19155 19156 workInProgress = workInProgress.return; 19157 } while (workInProgress !== null); 19158 } 19159 19160 function getSuspendedCache() { 19161 { 19162 return null; 19163 } // This function is called when a Suspense boundary suspends. It returns the 19164 } 19165 19166 var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; 19167 var didReceiveUpdate = false; 19168 var didWarnAboutBadClass; 19169 var didWarnAboutModulePatternComponent; 19170 var didWarnAboutContextTypeOnFunctionComponent; 19171 var didWarnAboutGetDerivedStateOnFunctionComponent; 19172 var didWarnAboutFunctionRefs; 19173 var didWarnAboutReassigningProps; 19174 var didWarnAboutRevealOrder; 19175 var didWarnAboutTailOptions; 19176 var didWarnAboutDefaultPropsOnFunctionComponent; 19177 19178 { 19179 didWarnAboutBadClass = {}; 19180 didWarnAboutModulePatternComponent = {}; 19181 didWarnAboutContextTypeOnFunctionComponent = {}; 19182 didWarnAboutGetDerivedStateOnFunctionComponent = {}; 19183 didWarnAboutFunctionRefs = {}; 19184 didWarnAboutReassigningProps = false; 19185 didWarnAboutRevealOrder = {}; 19186 didWarnAboutTailOptions = {}; 19187 didWarnAboutDefaultPropsOnFunctionComponent = {}; 19188 } 19189 19190 function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { 19191 if (current === null) { 19192 // If this is a fresh new component that hasn't been rendered yet, we 19193 // won't update its child set by applying minimal side-effects. Instead, 19194 // we will add them all to the child before it gets rendered. That means 19195 // we can optimize this reconciliation pass by not tracking side-effects. 19196 workInProgress.child = mountChildFibers(workInProgress, null, nextChildren, renderLanes); 19197 } else { 19198 // If the current child is the same as the work in progress, it means that 19199 // we haven't yet started any work on these children. Therefore, we use 19200 // the clone algorithm to create a copy of all the current children. 19201 // If we had any progressed work already, that is invalid at this point so 19202 // let's throw it out. 19203 workInProgress.child = reconcileChildFibers(workInProgress, current.child, nextChildren, renderLanes); 19204 } 19205 } 19206 19207 function forceUnmountCurrentAndReconcile(current, workInProgress, nextChildren, renderLanes) { 19208 // This function is fork of reconcileChildren. It's used in cases where we 19209 // want to reconcile without matching against the existing set. This has the 19210 // effect of all current children being unmounted; even if the type and key 19211 // are the same, the old child is unmounted and a new child is created. 19212 // 19213 // To do this, we're going to go through the reconcile algorithm twice. In 19214 // the first pass, we schedule a deletion for all the current children by 19215 // passing null. 19216 workInProgress.child = reconcileChildFibers(workInProgress, current.child, null, renderLanes); // In the second pass, we mount the new children. The trick here is that we 19217 // pass null in place of where we usually pass the current child set. This has 19218 // the effect of remounting all children regardless of whether their 19219 // identities match. 19220 19221 workInProgress.child = reconcileChildFibers(workInProgress, null, nextChildren, renderLanes); 19222 } 19223 19224 function updateForwardRef(current, workInProgress, Component, nextProps, renderLanes) { 19225 // TODO: current can be non-null here even if the component 19226 // hasn't yet mounted. This happens after the first render suspends. 19227 // We'll need to figure out if this is fine or can cause issues. 19228 { 19229 if (workInProgress.type !== workInProgress.elementType) { 19230 // Lazy component props can't be validated in createElement 19231 // because they're only guaranteed to be resolved here. 19232 var innerPropTypes = Component.propTypes; 19233 19234 if (innerPropTypes) { 19235 checkPropTypes(innerPropTypes, nextProps, // Resolved props 19236 'prop', getComponentNameFromType(Component)); 19237 } 19238 } 19239 } 19240 19241 var render = Component.render; 19242 var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent 19243 19244 var nextChildren; 19245 var hasId; 19246 prepareToReadContext(workInProgress, renderLanes); 19247 19248 { 19249 markComponentRenderStarted(workInProgress); 19250 } 19251 19252 { 19253 ReactCurrentOwner$1.current = workInProgress; 19254 setIsRendering(true); 19255 nextChildren = renderWithHooks(current, workInProgress, render, nextProps, ref, renderLanes); 19256 hasId = checkDidRenderIdHook(); 19257 19258 if ( workInProgress.mode & StrictLegacyMode) { 19259 setIsStrictModeForDevtools(true); 19260 19261 try { 19262 nextChildren = renderWithHooks(current, workInProgress, render, nextProps, ref, renderLanes); 19263 hasId = checkDidRenderIdHook(); 19264 } finally { 19265 setIsStrictModeForDevtools(false); 19266 } 19267 } 19268 19269 setIsRendering(false); 19270 } 19271 19272 { 19273 markComponentRenderStopped(); 19274 } 19275 19276 if (current !== null && !didReceiveUpdate) { 19277 bailoutHooks(current, workInProgress, renderLanes); 19278 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 19279 } 19280 19281 if (getIsHydrating() && hasId) { 19282 pushMaterializedTreeId(workInProgress); 19283 } // React DevTools reads this flag. 19284 19285 19286 workInProgress.flags |= PerformedWork; 19287 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19288 return workInProgress.child; 19289 } 19290 19291 function updateMemoComponent(current, workInProgress, Component, nextProps, renderLanes) { 19292 if (current === null) { 19293 var type = Component.type; 19294 19295 if (isSimpleFunctionComponent(type) && Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. 19296 Component.defaultProps === undefined) { 19297 var resolvedType = type; 19298 19299 { 19300 resolvedType = resolveFunctionForHotReloading(type); 19301 } // If this is a plain function component without default props, 19302 // and with only the default shallow comparison, we upgrade it 19303 // to a SimpleMemoComponent to allow fast path updates. 19304 19305 19306 workInProgress.tag = SimpleMemoComponent; 19307 workInProgress.type = resolvedType; 19308 19309 { 19310 validateFunctionComponentInDev(workInProgress, type); 19311 } 19312 19313 return updateSimpleMemoComponent(current, workInProgress, resolvedType, nextProps, renderLanes); 19314 } 19315 19316 { 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 if ( Component.defaultProps !== undefined) { 19327 var componentName = getComponentNameFromType(type) || 'Unknown'; 19328 19329 if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) { 19330 error('%s: Support for defaultProps will be removed from memo components ' + 'in a future major release. Use JavaScript default parameters instead.', componentName); 19331 19332 didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true; 19333 } 19334 } 19335 } 19336 19337 var child = createFiberFromTypeAndProps(Component.type, null, nextProps, workInProgress, workInProgress.mode, renderLanes); 19338 child.ref = workInProgress.ref; 19339 child.return = workInProgress; 19340 workInProgress.child = child; 19341 return child; 19342 } 19343 19344 { 19345 var _type = Component.type; 19346 var _innerPropTypes = _type.propTypes; 19347 19348 if (_innerPropTypes) { 19349 // Inner memo component props aren't currently validated in createElement. 19350 // We could move it there, but we'd still need this for lazy code path. 19351 checkPropTypes(_innerPropTypes, nextProps, // Resolved props 19352 'prop', getComponentNameFromType(_type)); 19353 } 19354 } 19355 19356 var currentChild = current.child; // This is always exactly one child 19357 19358 var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext(current, renderLanes); 19359 19360 if (!hasScheduledUpdateOrContext) { 19361 // This will be the props with resolved defaultProps, 19362 // unlike current.memoizedProps which will be the unresolved ones. 19363 var prevProps = currentChild.memoizedProps; // Default to shallow comparison 19364 19365 var compare = Component.compare; 19366 compare = compare !== null ? compare : shallowEqual; 19367 19368 if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { 19369 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 19370 } 19371 } // React DevTools reads this flag. 19372 19373 19374 workInProgress.flags |= PerformedWork; 19375 var newChild = createWorkInProgress(currentChild, nextProps); 19376 newChild.ref = workInProgress.ref; 19377 newChild.return = workInProgress; 19378 workInProgress.child = newChild; 19379 return newChild; 19380 } 19381 19382 function updateSimpleMemoComponent(current, workInProgress, Component, nextProps, renderLanes) { 19383 // TODO: current can be non-null here even if the component 19384 // hasn't yet mounted. This happens when the inner render suspends. 19385 // We'll need to figure out if this is fine or can cause issues. 19386 { 19387 if (workInProgress.type !== workInProgress.elementType) { 19388 // Lazy component props can't be validated in createElement 19389 // because they're only guaranteed to be resolved here. 19390 var outerMemoType = workInProgress.elementType; 19391 19392 if (outerMemoType.$$typeof === REACT_LAZY_TYPE) { 19393 // We warn when you define propTypes on lazy() 19394 // so let's just skip over it to find memo() outer wrapper. 19395 // Inner props for memo are validated later. 19396 var lazyComponent = outerMemoType; 19397 var payload = lazyComponent._payload; 19398 var init = lazyComponent._init; 19399 19400 try { 19401 outerMemoType = init(payload); 19402 } catch (x) { 19403 outerMemoType = null; 19404 } // Inner propTypes will be validated in the function component path. 19405 19406 19407 var outerPropTypes = outerMemoType && outerMemoType.propTypes; 19408 19409 if (outerPropTypes) { 19410 checkPropTypes(outerPropTypes, nextProps, // Resolved (SimpleMemoComponent has no defaultProps) 19411 'prop', getComponentNameFromType(outerMemoType)); 19412 } 19413 } 19414 } 19415 } 19416 19417 if (current !== null) { 19418 var prevProps = current.memoizedProps; 19419 19420 if (shallowEqual(prevProps, nextProps) && current.ref === workInProgress.ref && ( // Prevent bailout if the implementation changed due to hot reload. 19421 workInProgress.type === current.type )) { 19422 didReceiveUpdate = false; // The props are shallowly equal. Reuse the previous props object, like we 19423 // would during a normal fiber bailout. 19424 // 19425 // We don't have strong guarantees that the props object is referentially 19426 // equal during updates where we can't bail out anyway — like if the props 19427 // are shallowly equal, but there's a local state or context update in the 19428 // same batch. 19429 // 19430 // However, as a principle, we should aim to make the behavior consistent 19431 // across different ways of memoizing a component. For example, React.memo 19432 // has a different internal Fiber layout if you pass a normal function 19433 // component (SimpleMemoComponent) versus if you pass a different type 19434 // like forwardRef (MemoComponent). But this is an implementation detail. 19435 // Wrapping a component in forwardRef (or React.lazy, etc) shouldn't 19436 // affect whether the props object is reused during a bailout. 19437 19438 workInProgress.pendingProps = nextProps = prevProps; 19439 19440 if (!checkScheduledUpdateOrContext(current, renderLanes)) { 19441 // The pending lanes were cleared at the beginning of beginWork. We're 19442 // about to bail out, but there might be other lanes that weren't 19443 // included in the current render. Usually, the priority level of the 19444 // remaining updates is accumulated during the evaluation of the 19445 // component (i.e. when processing the update queue). But since since 19446 // we're bailing out early *without* evaluating the component, we need 19447 // to account for it here, too. Reset to the value of the current fiber. 19448 // NOTE: This only applies to SimpleMemoComponent, not MemoComponent, 19449 // because a MemoComponent fiber does not have hooks or an update queue; 19450 // rather, it wraps around an inner component, which may or may not 19451 // contains hooks. 19452 // TODO: Move the reset at in beginWork out of the common path so that 19453 // this is no longer necessary. 19454 workInProgress.lanes = current.lanes; 19455 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 19456 } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { 19457 // This is a special case that only exists for legacy mode. 19458 // See https://github.com/facebook/react/pull/19216. 19459 didReceiveUpdate = true; 19460 } 19461 } 19462 } 19463 19464 return updateFunctionComponent(current, workInProgress, Component, nextProps, renderLanes); 19465 } 19466 19467 function updateOffscreenComponent(current, workInProgress, renderLanes) { 19468 var nextProps = workInProgress.pendingProps; 19469 var nextChildren = nextProps.children; 19470 var prevState = current !== null ? current.memoizedState : null; 19471 19472 if (nextProps.mode === 'hidden' || enableLegacyHidden ) { 19473 // Rendering a hidden tree. 19474 if ((workInProgress.mode & ConcurrentMode) === NoMode) { 19475 // In legacy sync mode, don't defer the subtree. Render it now. 19476 // TODO: Consider how Offscreen should work with transitions in the future 19477 var nextState = { 19478 baseLanes: NoLanes, 19479 cachePool: null, 19480 transitions: null 19481 }; 19482 workInProgress.memoizedState = nextState; 19483 19484 pushRenderLanes(workInProgress, renderLanes); 19485 } else if (!includesSomeLane(renderLanes, OffscreenLane)) { 19486 var spawnedCachePool = null; // We're hidden, and we're not rendering at Offscreen. We will bail out 19487 // and resume this tree later. 19488 19489 var nextBaseLanes; 19490 19491 if (prevState !== null) { 19492 var prevBaseLanes = prevState.baseLanes; 19493 nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); 19494 } else { 19495 nextBaseLanes = renderLanes; 19496 } // Schedule this fiber to re-render at offscreen priority. Then bailout. 19497 19498 19499 workInProgress.lanes = workInProgress.childLanes = laneToLanes(OffscreenLane); 19500 var _nextState = { 19501 baseLanes: nextBaseLanes, 19502 cachePool: spawnedCachePool, 19503 transitions: null 19504 }; 19505 workInProgress.memoizedState = _nextState; 19506 workInProgress.updateQueue = null; 19507 // to avoid a push/pop misalignment. 19508 19509 19510 pushRenderLanes(workInProgress, nextBaseLanes); 19511 19512 return null; 19513 } else { 19514 // This is the second render. The surrounding visible content has already 19515 // committed. Now we resume rendering the hidden tree. 19516 // Rendering at offscreen, so we can clear the base lanes. 19517 var _nextState2 = { 19518 baseLanes: NoLanes, 19519 cachePool: null, 19520 transitions: null 19521 }; 19522 workInProgress.memoizedState = _nextState2; // Push the lanes that were skipped when we bailed out. 19523 19524 var subtreeRenderLanes = prevState !== null ? prevState.baseLanes : renderLanes; 19525 19526 pushRenderLanes(workInProgress, subtreeRenderLanes); 19527 } 19528 } else { 19529 // Rendering a visible tree. 19530 var _subtreeRenderLanes; 19531 19532 if (prevState !== null) { 19533 // We're going from hidden -> visible. 19534 _subtreeRenderLanes = mergeLanes(prevState.baseLanes, renderLanes); 19535 19536 workInProgress.memoizedState = null; 19537 } else { 19538 // We weren't previously hidden, and we still aren't, so there's nothing 19539 // special to do. Need to push to the stack regardless, though, to avoid 19540 // a push/pop misalignment. 19541 _subtreeRenderLanes = renderLanes; 19542 } 19543 19544 pushRenderLanes(workInProgress, _subtreeRenderLanes); 19545 } 19546 19547 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19548 return workInProgress.child; 19549 } // Note: These happen to have identical begin phases, for now. We shouldn't hold 19550 19551 function updateFragment(current, workInProgress, renderLanes) { 19552 var nextChildren = workInProgress.pendingProps; 19553 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19554 return workInProgress.child; 19555 } 19556 19557 function updateMode(current, workInProgress, renderLanes) { 19558 var nextChildren = workInProgress.pendingProps.children; 19559 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19560 return workInProgress.child; 19561 } 19562 19563 function updateProfiler(current, workInProgress, renderLanes) { 19564 { 19565 workInProgress.flags |= Update; 19566 19567 { 19568 // Reset effect durations for the next eventual effect phase. 19569 // These are reset during render to allow the DevTools commit hook a chance to read them, 19570 var stateNode = workInProgress.stateNode; 19571 stateNode.effectDuration = 0; 19572 stateNode.passiveEffectDuration = 0; 19573 } 19574 } 19575 19576 var nextProps = workInProgress.pendingProps; 19577 var nextChildren = nextProps.children; 19578 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19579 return workInProgress.child; 19580 } 19581 19582 function markRef(current, workInProgress) { 19583 var ref = workInProgress.ref; 19584 19585 if (current === null && ref !== null || current !== null && current.ref !== ref) { 19586 // Schedule a Ref effect 19587 workInProgress.flags |= Ref; 19588 19589 { 19590 workInProgress.flags |= RefStatic; 19591 } 19592 } 19593 } 19594 19595 function updateFunctionComponent(current, workInProgress, Component, nextProps, renderLanes) { 19596 { 19597 if (workInProgress.type !== workInProgress.elementType) { 19598 // Lazy component props can't be validated in createElement 19599 // because they're only guaranteed to be resolved here. 19600 var innerPropTypes = Component.propTypes; 19601 19602 if (innerPropTypes) { 19603 checkPropTypes(innerPropTypes, nextProps, // Resolved props 19604 'prop', getComponentNameFromType(Component)); 19605 } 19606 } 19607 } 19608 19609 var context; 19610 19611 { 19612 var unmaskedContext = getUnmaskedContext(workInProgress, Component, true); 19613 context = getMaskedContext(workInProgress, unmaskedContext); 19614 } 19615 19616 var nextChildren; 19617 var hasId; 19618 prepareToReadContext(workInProgress, renderLanes); 19619 19620 { 19621 markComponentRenderStarted(workInProgress); 19622 } 19623 19624 { 19625 ReactCurrentOwner$1.current = workInProgress; 19626 setIsRendering(true); 19627 nextChildren = renderWithHooks(current, workInProgress, Component, nextProps, context, renderLanes); 19628 hasId = checkDidRenderIdHook(); 19629 19630 if ( workInProgress.mode & StrictLegacyMode) { 19631 setIsStrictModeForDevtools(true); 19632 19633 try { 19634 nextChildren = renderWithHooks(current, workInProgress, Component, nextProps, context, renderLanes); 19635 hasId = checkDidRenderIdHook(); 19636 } finally { 19637 setIsStrictModeForDevtools(false); 19638 } 19639 } 19640 19641 setIsRendering(false); 19642 } 19643 19644 { 19645 markComponentRenderStopped(); 19646 } 19647 19648 if (current !== null && !didReceiveUpdate) { 19649 bailoutHooks(current, workInProgress, renderLanes); 19650 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 19651 } 19652 19653 if (getIsHydrating() && hasId) { 19654 pushMaterializedTreeId(workInProgress); 19655 } // React DevTools reads this flag. 19656 19657 19658 workInProgress.flags |= PerformedWork; 19659 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19660 return workInProgress.child; 19661 } 19662 19663 function updateClassComponent(current, workInProgress, Component, nextProps, renderLanes) { 19664 { 19665 // This is used by DevTools to force a boundary to error. 19666 switch (shouldError(workInProgress)) { 19667 case false: 19668 { 19669 var _instance = workInProgress.stateNode; 19670 var ctor = workInProgress.type; // TODO This way of resetting the error boundary state is a hack. 19671 // Is there a better way to do this? 19672 19673 var tempInstance = new ctor(workInProgress.memoizedProps, _instance.context); 19674 var state = tempInstance.state; 19675 19676 _instance.updater.enqueueSetState(_instance, state, null); 19677 19678 break; 19679 } 19680 19681 case true: 19682 { 19683 workInProgress.flags |= DidCapture; 19684 workInProgress.flags |= ShouldCapture; // eslint-disable-next-line react-internal/prod-error-codes 19685 19686 var error$1 = new Error('Simulated error coming from DevTools'); 19687 var lane = pickArbitraryLane(renderLanes); 19688 workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); // Schedule the error boundary to re-render using updated state 19689 19690 var update = createClassErrorUpdate(workInProgress, createCapturedValueAtFiber(error$1, workInProgress), lane); 19691 enqueueCapturedUpdate(workInProgress, update); 19692 break; 19693 } 19694 } 19695 19696 if (workInProgress.type !== workInProgress.elementType) { 19697 // Lazy component props can't be validated in createElement 19698 // because they're only guaranteed to be resolved here. 19699 var innerPropTypes = Component.propTypes; 19700 19701 if (innerPropTypes) { 19702 checkPropTypes(innerPropTypes, nextProps, // Resolved props 19703 'prop', getComponentNameFromType(Component)); 19704 } 19705 } 19706 } // Push context providers early to prevent context stack mismatches. 19707 // During mounting we don't know the child context yet as the instance doesn't exist. 19708 // We will invalidate the child context in finishClassComponent() right after rendering. 19709 19710 19711 var hasContext; 19712 19713 if (isContextProvider(Component)) { 19714 hasContext = true; 19715 pushContextProvider(workInProgress); 19716 } else { 19717 hasContext = false; 19718 } 19719 19720 prepareToReadContext(workInProgress, renderLanes); 19721 var instance = workInProgress.stateNode; 19722 var shouldUpdate; 19723 19724 if (instance === null) { 19725 resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); // In the initial pass we might need to construct the instance. 19726 19727 constructClassInstance(workInProgress, Component, nextProps); 19728 mountClassInstance(workInProgress, Component, nextProps, renderLanes); 19729 shouldUpdate = true; 19730 } else if (current === null) { 19731 // In a resume, we'll already have an instance we can reuse. 19732 shouldUpdate = resumeMountClassInstance(workInProgress, Component, nextProps, renderLanes); 19733 } else { 19734 shouldUpdate = updateClassInstance(current, workInProgress, Component, nextProps, renderLanes); 19735 } 19736 19737 var nextUnitOfWork = finishClassComponent(current, workInProgress, Component, shouldUpdate, hasContext, renderLanes); 19738 19739 { 19740 var inst = workInProgress.stateNode; 19741 19742 if (shouldUpdate && inst.props !== nextProps) { 19743 if (!didWarnAboutReassigningProps) { 19744 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'); 19745 } 19746 19747 didWarnAboutReassigningProps = true; 19748 } 19749 } 19750 19751 return nextUnitOfWork; 19752 } 19753 19754 function finishClassComponent(current, workInProgress, Component, shouldUpdate, hasContext, renderLanes) { 19755 // Refs should update even if shouldComponentUpdate returns false 19756 markRef(current, workInProgress); 19757 var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags; 19758 19759 if (!shouldUpdate && !didCaptureError) { 19760 // Context providers should defer to sCU for rendering 19761 if (hasContext) { 19762 invalidateContextProvider(workInProgress, Component, false); 19763 } 19764 19765 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 19766 } 19767 19768 var instance = workInProgress.stateNode; // Rerender 19769 19770 ReactCurrentOwner$1.current = workInProgress; 19771 var nextChildren; 19772 19773 if (didCaptureError && typeof Component.getDerivedStateFromError !== 'function') { 19774 // If we captured an error, but getDerivedStateFromError is not defined, 19775 // unmount all the children. componentDidCatch will schedule an update to 19776 // re-render a fallback. This is temporary until we migrate everyone to 19777 // the new API. 19778 // TODO: Warn in a future release. 19779 nextChildren = null; 19780 19781 { 19782 stopProfilerTimerIfRunning(); 19783 } 19784 } else { 19785 { 19786 markComponentRenderStarted(workInProgress); 19787 } 19788 19789 { 19790 setIsRendering(true); 19791 nextChildren = instance.render(); 19792 19793 if ( workInProgress.mode & StrictLegacyMode) { 19794 setIsStrictModeForDevtools(true); 19795 19796 try { 19797 instance.render(); 19798 } finally { 19799 setIsStrictModeForDevtools(false); 19800 } 19801 } 19802 19803 setIsRendering(false); 19804 } 19805 19806 { 19807 markComponentRenderStopped(); 19808 } 19809 } // React DevTools reads this flag. 19810 19811 19812 workInProgress.flags |= PerformedWork; 19813 19814 if (current !== null && didCaptureError) { 19815 // If we're recovering from an error, reconcile without reusing any of 19816 // the existing children. Conceptually, the normal children and the children 19817 // that are shown on error are two different sets, so we shouldn't reuse 19818 // normal children even if their identities match. 19819 forceUnmountCurrentAndReconcile(current, workInProgress, nextChildren, renderLanes); 19820 } else { 19821 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19822 } // Memoize state using the values we just used to render. 19823 // TODO: Restructure so we never read values from the instance. 19824 19825 19826 workInProgress.memoizedState = instance.state; // The context might have changed so we need to recalculate it. 19827 19828 if (hasContext) { 19829 invalidateContextProvider(workInProgress, Component, true); 19830 } 19831 19832 return workInProgress.child; 19833 } 19834 19835 function pushHostRootContext(workInProgress) { 19836 var root = workInProgress.stateNode; 19837 19838 if (root.pendingContext) { 19839 pushTopLevelContextObject(workInProgress, root.pendingContext, root.pendingContext !== root.context); 19840 } else if (root.context) { 19841 // Should always be set 19842 pushTopLevelContextObject(workInProgress, root.context, false); 19843 } 19844 19845 pushHostContainer(workInProgress, root.containerInfo); 19846 } 19847 19848 function updateHostRoot(current, workInProgress, renderLanes) { 19849 pushHostRootContext(workInProgress); 19850 19851 if (current === null) { 19852 throw new Error('Should have a current fiber. This is a bug in React.'); 19853 } 19854 19855 var nextProps = workInProgress.pendingProps; 19856 var prevState = workInProgress.memoizedState; 19857 var prevChildren = prevState.element; 19858 cloneUpdateQueue(current, workInProgress); 19859 processUpdateQueue(workInProgress, nextProps, null, renderLanes); 19860 var nextState = workInProgress.memoizedState; 19861 var root = workInProgress.stateNode; 19862 // being called "element". 19863 19864 19865 var nextChildren = nextState.element; 19866 19867 if ( prevState.isDehydrated) { 19868 // This is a hydration root whose shell has not yet hydrated. We should 19869 // attempt to hydrate. 19870 // Flip isDehydrated to false to indicate that when this render 19871 // finishes, the root will no longer be dehydrated. 19872 var overrideState = { 19873 element: nextChildren, 19874 isDehydrated: false, 19875 cache: nextState.cache, 19876 pendingSuspenseBoundaries: nextState.pendingSuspenseBoundaries, 19877 transitions: nextState.transitions 19878 }; 19879 var updateQueue = workInProgress.updateQueue; // `baseState` can always be the last state because the root doesn't 19880 // have reducer functions so it doesn't need rebasing. 19881 19882 updateQueue.baseState = overrideState; 19883 workInProgress.memoizedState = overrideState; 19884 19885 if (workInProgress.flags & ForceClientRender) { 19886 // Something errored during a previous attempt to hydrate the shell, so we 19887 // forced a client render. 19888 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); 19889 return mountHostRootWithoutHydrating(current, workInProgress, nextChildren, renderLanes, recoverableError); 19890 } else if (nextChildren !== prevChildren) { 19891 var _recoverableError = createCapturedValueAtFiber(new Error('This root received an early update, before anything was able ' + 'hydrate. Switched the entire root to client rendering.'), workInProgress); 19892 19893 return mountHostRootWithoutHydrating(current, workInProgress, nextChildren, renderLanes, _recoverableError); 19894 } else { 19895 // The outermost shell has not hydrated yet. Start hydrating. 19896 enterHydrationState(workInProgress); 19897 19898 var child = mountChildFibers(workInProgress, null, nextChildren, renderLanes); 19899 workInProgress.child = child; 19900 var node = child; 19901 19902 while (node) { 19903 // Mark each child as hydrating. This is a fast path to know whether this 19904 // tree is part of a hydrating tree. This is used to determine if a child 19905 // node has fully mounted yet, and for scheduling event replaying. 19906 // Conceptually this is similar to Placement in that a new subtree is 19907 // inserted into the React tree here. It just happens to not need DOM 19908 // mutations because it already exists. 19909 node.flags = node.flags & ~Placement | Hydrating; 19910 node = node.sibling; 19911 } 19912 } 19913 } else { 19914 // Root is not dehydrated. Either this is a client-only root, or it 19915 // already hydrated. 19916 resetHydrationState(); 19917 19918 if (nextChildren === prevChildren) { 19919 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 19920 } 19921 19922 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19923 } 19924 19925 return workInProgress.child; 19926 } 19927 19928 function mountHostRootWithoutHydrating(current, workInProgress, nextChildren, renderLanes, recoverableError) { 19929 // Revert to client rendering. 19930 resetHydrationState(); 19931 queueHydrationError(recoverableError); 19932 workInProgress.flags |= ForceClientRender; 19933 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19934 return workInProgress.child; 19935 } 19936 19937 function updateHostComponent(current, workInProgress, renderLanes) { 19938 pushHostContext(workInProgress); 19939 19940 if (current === null) { 19941 tryToClaimNextHydratableInstance(workInProgress); 19942 } 19943 19944 var type = workInProgress.type; 19945 var nextProps = workInProgress.pendingProps; 19946 var prevProps = current !== null ? current.memoizedProps : null; 19947 var nextChildren = nextProps.children; 19948 var isDirectTextChild = shouldSetTextContent(type, nextProps); 19949 19950 if (isDirectTextChild) { 19951 // We special case a direct text child of a host node. This is a common 19952 // case. We won't handle it as a reified child. We will instead handle 19953 // this in the host environment that also has access to this prop. That 19954 // avoids allocating another HostText fiber and traversing it. 19955 nextChildren = null; 19956 } else if (prevProps !== null && shouldSetTextContent(type, prevProps)) { 19957 // If we're switching from a direct text child to a normal child, or to 19958 // empty, we need to schedule the text content to be reset. 19959 workInProgress.flags |= ContentReset; 19960 } 19961 19962 markRef(current, workInProgress); 19963 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19964 return workInProgress.child; 19965 } 19966 19967 function updateHostText(current, workInProgress) { 19968 if (current === null) { 19969 tryToClaimNextHydratableInstance(workInProgress); 19970 } // Nothing to do here. This is terminal. We'll do the completion step 19971 // immediately after. 19972 19973 19974 return null; 19975 } 19976 19977 function mountLazyComponent(_current, workInProgress, elementType, renderLanes) { 19978 resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); 19979 var props = workInProgress.pendingProps; 19980 var lazyComponent = elementType; 19981 var payload = lazyComponent._payload; 19982 var init = lazyComponent._init; 19983 var Component = init(payload); // Store the unwrapped component in the type. 19984 19985 workInProgress.type = Component; 19986 var resolvedTag = workInProgress.tag = resolveLazyComponentTag(Component); 19987 var resolvedProps = resolveDefaultProps(Component, props); 19988 var child; 19989 19990 switch (resolvedTag) { 19991 case FunctionComponent: 19992 { 19993 { 19994 validateFunctionComponentInDev(workInProgress, Component); 19995 workInProgress.type = Component = resolveFunctionForHotReloading(Component); 19996 } 19997 19998 child = updateFunctionComponent(null, workInProgress, Component, resolvedProps, renderLanes); 19999 return child; 20000 } 20001 20002 case ClassComponent: 20003 { 20004 { 20005 workInProgress.type = Component = resolveClassForHotReloading(Component); 20006 } 20007 20008 child = updateClassComponent(null, workInProgress, Component, resolvedProps, renderLanes); 20009 return child; 20010 } 20011 20012 case ForwardRef: 20013 { 20014 { 20015 workInProgress.type = Component = resolveForwardRefForHotReloading(Component); 20016 } 20017 20018 child = updateForwardRef(null, workInProgress, Component, resolvedProps, renderLanes); 20019 return child; 20020 } 20021 20022 case MemoComponent: 20023 { 20024 { 20025 if (workInProgress.type !== workInProgress.elementType) { 20026 var outerPropTypes = Component.propTypes; 20027 20028 if (outerPropTypes) { 20029 checkPropTypes(outerPropTypes, resolvedProps, // Resolved for outer only 20030 'prop', getComponentNameFromType(Component)); 20031 } 20032 } 20033 } 20034 20035 child = updateMemoComponent(null, workInProgress, Component, resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too 20036 renderLanes); 20037 return child; 20038 } 20039 } 20040 20041 var hint = ''; 20042 20043 { 20044 if (Component !== null && typeof Component === 'object' && Component.$$typeof === REACT_LAZY_TYPE) { 20045 hint = ' Did you wrap a component in React.lazy() more than once?'; 20046 } 20047 } // This message intentionally doesn't mention ForwardRef or MemoComponent 20048 // because the fact that it's a separate type of work is an 20049 // implementation detail. 20050 20051 20052 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)); 20053 } 20054 20055 function mountIncompleteClassComponent(_current, workInProgress, Component, nextProps, renderLanes) { 20056 resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); // Promote the fiber to a class and try rendering again. 20057 20058 workInProgress.tag = ClassComponent; // The rest of this function is a fork of `updateClassComponent` 20059 // Push context providers early to prevent context stack mismatches. 20060 // During mounting we don't know the child context yet as the instance doesn't exist. 20061 // We will invalidate the child context in finishClassComponent() right after rendering. 20062 20063 var hasContext; 20064 20065 if (isContextProvider(Component)) { 20066 hasContext = true; 20067 pushContextProvider(workInProgress); 20068 } else { 20069 hasContext = false; 20070 } 20071 20072 prepareToReadContext(workInProgress, renderLanes); 20073 constructClassInstance(workInProgress, Component, nextProps); 20074 mountClassInstance(workInProgress, Component, nextProps, renderLanes); 20075 return finishClassComponent(null, workInProgress, Component, true, hasContext, renderLanes); 20076 } 20077 20078 function mountIndeterminateComponent(_current, workInProgress, Component, renderLanes) { 20079 resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); 20080 var props = workInProgress.pendingProps; 20081 var context; 20082 20083 { 20084 var unmaskedContext = getUnmaskedContext(workInProgress, Component, false); 20085 context = getMaskedContext(workInProgress, unmaskedContext); 20086 } 20087 20088 prepareToReadContext(workInProgress, renderLanes); 20089 var value; 20090 var hasId; 20091 20092 { 20093 markComponentRenderStarted(workInProgress); 20094 } 20095 20096 { 20097 if (Component.prototype && typeof Component.prototype.render === 'function') { 20098 var componentName = getComponentNameFromType(Component) || 'Unknown'; 20099 20100 if (!didWarnAboutBadClass[componentName]) { 20101 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); 20102 20103 didWarnAboutBadClass[componentName] = true; 20104 } 20105 } 20106 20107 if (workInProgress.mode & StrictLegacyMode) { 20108 ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null); 20109 } 20110 20111 setIsRendering(true); 20112 ReactCurrentOwner$1.current = workInProgress; 20113 value = renderWithHooks(null, workInProgress, Component, props, context, renderLanes); 20114 hasId = checkDidRenderIdHook(); 20115 setIsRendering(false); 20116 } 20117 20118 { 20119 markComponentRenderStopped(); 20120 } // React DevTools reads this flag. 20121 20122 20123 workInProgress.flags |= PerformedWork; 20124 20125 { 20126 // Support for module components is deprecated and is removed behind a flag. 20127 // Whether or not it would crash later, we want to show a good message in DEV first. 20128 if (typeof value === 'object' && value !== null && typeof value.render === 'function' && value.$$typeof === undefined) { 20129 var _componentName = getComponentNameFromType(Component) || 'Unknown'; 20130 20131 if (!didWarnAboutModulePatternComponent[_componentName]) { 20132 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); 20133 20134 didWarnAboutModulePatternComponent[_componentName] = true; 20135 } 20136 } 20137 } 20138 20139 if ( // Run these checks in production only if the flag is off. 20140 // Eventually we'll delete this branch altogether. 20141 typeof value === 'object' && value !== null && typeof value.render === 'function' && value.$$typeof === undefined) { 20142 { 20143 var _componentName2 = getComponentNameFromType(Component) || 'Unknown'; 20144 20145 if (!didWarnAboutModulePatternComponent[_componentName2]) { 20146 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); 20147 20148 didWarnAboutModulePatternComponent[_componentName2] = true; 20149 } 20150 } // Proceed under the assumption that this is a class instance 20151 20152 20153 workInProgress.tag = ClassComponent; // Throw out any hooks that were used. 20154 20155 workInProgress.memoizedState = null; 20156 workInProgress.updateQueue = null; // Push context providers early to prevent context stack mismatches. 20157 // During mounting we don't know the child context yet as the instance doesn't exist. 20158 // We will invalidate the child context in finishClassComponent() right after rendering. 20159 20160 var hasContext = false; 20161 20162 if (isContextProvider(Component)) { 20163 hasContext = true; 20164 pushContextProvider(workInProgress); 20165 } else { 20166 hasContext = false; 20167 } 20168 20169 workInProgress.memoizedState = value.state !== null && value.state !== undefined ? value.state : null; 20170 initializeUpdateQueue(workInProgress); 20171 adoptClassInstance(workInProgress, value); 20172 mountClassInstance(workInProgress, Component, props, renderLanes); 20173 return finishClassComponent(null, workInProgress, Component, true, hasContext, renderLanes); 20174 } else { 20175 // Proceed under the assumption that this is a function component 20176 workInProgress.tag = FunctionComponent; 20177 20178 { 20179 20180 if ( workInProgress.mode & StrictLegacyMode) { 20181 setIsStrictModeForDevtools(true); 20182 20183 try { 20184 value = renderWithHooks(null, workInProgress, Component, props, context, renderLanes); 20185 hasId = checkDidRenderIdHook(); 20186 } finally { 20187 setIsStrictModeForDevtools(false); 20188 } 20189 } 20190 } 20191 20192 if (getIsHydrating() && hasId) { 20193 pushMaterializedTreeId(workInProgress); 20194 } 20195 20196 reconcileChildren(null, workInProgress, value, renderLanes); 20197 20198 { 20199 validateFunctionComponentInDev(workInProgress, Component); 20200 } 20201 20202 return workInProgress.child; 20203 } 20204 } 20205 20206 function validateFunctionComponentInDev(workInProgress, Component) { 20207 { 20208 if (Component) { 20209 if (Component.childContextTypes) { 20210 error('%s(...): childContextTypes cannot be defined on a function component.', Component.displayName || Component.name || 'Component'); 20211 } 20212 } 20213 20214 if (workInProgress.ref !== null) { 20215 var info = ''; 20216 var ownerName = getCurrentFiberOwnerNameInDevOrNull(); 20217 20218 if (ownerName) { 20219 info += '\n\nCheck the render method of `' + ownerName + '`.'; 20220 } 20221 20222 var warningKey = ownerName || ''; 20223 var debugSource = workInProgress._debugSource; 20224 20225 if (debugSource) { 20226 warningKey = debugSource.fileName + ':' + debugSource.lineNumber; 20227 } 20228 20229 if (!didWarnAboutFunctionRefs[warningKey]) { 20230 didWarnAboutFunctionRefs[warningKey] = true; 20231 20232 error('Function components cannot be given refs. ' + 'Attempts to access this ref will fail. ' + 'Did you mean to use React.forwardRef()?%s', info); 20233 } 20234 } 20235 20236 if ( Component.defaultProps !== undefined) { 20237 var componentName = getComponentNameFromType(Component) || 'Unknown'; 20238 20239 if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) { 20240 error('%s: Support for defaultProps will be removed from function components ' + 'in a future major release. Use JavaScript default parameters instead.', componentName); 20241 20242 didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true; 20243 } 20244 } 20245 20246 if (typeof Component.getDerivedStateFromProps === 'function') { 20247 var _componentName3 = getComponentNameFromType(Component) || 'Unknown'; 20248 20249 if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { 20250 error('%s: Function components do not support getDerivedStateFromProps.', _componentName3); 20251 20252 didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true; 20253 } 20254 } 20255 20256 if (typeof Component.contextType === 'object' && Component.contextType !== null) { 20257 var _componentName4 = getComponentNameFromType(Component) || 'Unknown'; 20258 20259 if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { 20260 error('%s: Function components do not support contextType.', _componentName4); 20261 20262 didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; 20263 } 20264 } 20265 } 20266 } 20267 20268 var SUSPENDED_MARKER = { 20269 dehydrated: null, 20270 treeContext: null, 20271 retryLane: NoLane 20272 }; 20273 20274 function mountSuspenseOffscreenState(renderLanes) { 20275 return { 20276 baseLanes: renderLanes, 20277 cachePool: getSuspendedCache(), 20278 transitions: null 20279 }; 20280 } 20281 20282 function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { 20283 var cachePool = null; 20284 20285 return { 20286 baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), 20287 cachePool: cachePool, 20288 transitions: prevOffscreenState.transitions 20289 }; 20290 } // TODO: Probably should inline this back 20291 20292 20293 function shouldRemainOnFallback(suspenseContext, current, workInProgress, renderLanes) { 20294 // If we're already showing a fallback, there are cases where we need to 20295 // remain on that fallback regardless of whether the content has resolved. 20296 // For example, SuspenseList coordinates when nested content appears. 20297 if (current !== null) { 20298 var suspenseState = current.memoizedState; 20299 20300 if (suspenseState === null) { 20301 // Currently showing content. Don't hide it, even if ForceSuspenseFallback 20302 // is true. More precise name might be "ForceRemainSuspenseFallback". 20303 // Note: This is a factoring smell. Can't remain on a fallback if there's 20304 // no fallback to remain on. 20305 return false; 20306 } 20307 } // Not currently showing content. Consult the Suspense context. 20308 20309 20310 return hasSuspenseContext(suspenseContext, ForceSuspenseFallback); 20311 } 20312 20313 function getRemainingWorkInPrimaryTree(current, renderLanes) { 20314 // TODO: Should not remove render lanes that were pinged during this render 20315 return removeLanes(current.childLanes, renderLanes); 20316 } 20317 20318 function updateSuspenseComponent(current, workInProgress, renderLanes) { 20319 var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend. 20320 20321 { 20322 if (shouldSuspend(workInProgress)) { 20323 workInProgress.flags |= DidCapture; 20324 } 20325 } 20326 20327 var suspenseContext = suspenseStackCursor.current; 20328 var showFallback = false; 20329 var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags; 20330 20331 if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) { 20332 // Something in this boundary's subtree already suspended. Switch to 20333 // rendering the fallback children. 20334 showFallback = true; 20335 workInProgress.flags &= ~DidCapture; 20336 } else { 20337 // Attempting the main content 20338 if (current === null || current.memoizedState !== null) { 20339 // This is a new mount or this boundary is already showing a fallback state. 20340 // Mark this subtree context as having at least one invisible parent that could 20341 // handle the fallback state. 20342 // Avoided boundaries are not considered since they cannot handle preferred fallback states. 20343 { 20344 suspenseContext = addSubtreeSuspenseContext(suspenseContext, InvisibleParentSuspenseContext); 20345 } 20346 } 20347 } 20348 20349 suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); 20350 pushSuspenseContext(workInProgress, suspenseContext); // OK, the next part is confusing. We're about to reconcile the Suspense 20351 // boundary's children. This involves some custom reconciliation logic. Two 20352 // main reasons this is so complicated. 20353 // 20354 // First, Legacy Mode has different semantics for backwards compatibility. The 20355 // primary tree will commit in an inconsistent state, so when we do the 20356 // second pass to render the fallback, we do some exceedingly, uh, clever 20357 // hacks to make that not totally break. Like transferring effects and 20358 // deletions from hidden tree. In Concurrent Mode, it's much simpler, 20359 // because we bailout on the primary tree completely and leave it in its old 20360 // state, no effects. Same as what we do for Offscreen (except that 20361 // Offscreen doesn't have the first render pass). 20362 // 20363 // Second is hydration. During hydration, the Suspense fiber has a slightly 20364 // different layout, where the child points to a dehydrated fragment, which 20365 // contains the DOM rendered by the server. 20366 // 20367 // Third, even if you set all that aside, Suspense is like error boundaries in 20368 // that we first we try to render one tree, and if that fails, we render again 20369 // and switch to a different tree. Like a try/catch block. So we have to track 20370 // which branch we're currently rendering. Ideally we would model this using 20371 // a stack. 20372 20373 if (current === null) { 20374 // Initial mount 20375 // Special path for hydration 20376 // If we're currently hydrating, try to hydrate this boundary. 20377 tryToClaimNextHydratableInstance(workInProgress); // This could've been a dehydrated suspense component. 20378 20379 var suspenseState = workInProgress.memoizedState; 20380 20381 if (suspenseState !== null) { 20382 var dehydrated = suspenseState.dehydrated; 20383 20384 if (dehydrated !== null) { 20385 return mountDehydratedSuspenseComponent(workInProgress, dehydrated); 20386 } 20387 } 20388 20389 var nextPrimaryChildren = nextProps.children; 20390 var nextFallbackChildren = nextProps.fallback; 20391 20392 if (showFallback) { 20393 var fallbackFragment = mountSuspenseFallbackChildren(workInProgress, nextPrimaryChildren, nextFallbackChildren, renderLanes); 20394 var primaryChildFragment = workInProgress.child; 20395 primaryChildFragment.memoizedState = mountSuspenseOffscreenState(renderLanes); 20396 workInProgress.memoizedState = SUSPENDED_MARKER; 20397 20398 return fallbackFragment; 20399 } else { 20400 return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren); 20401 } 20402 } else { 20403 // This is an update. 20404 // Special path for hydration 20405 var prevState = current.memoizedState; 20406 20407 if (prevState !== null) { 20408 var _dehydrated = prevState.dehydrated; 20409 20410 if (_dehydrated !== null) { 20411 return updateDehydratedSuspenseComponent(current, workInProgress, didSuspend, nextProps, _dehydrated, prevState, renderLanes); 20412 } 20413 } 20414 20415 if (showFallback) { 20416 var _nextFallbackChildren = nextProps.fallback; 20417 var _nextPrimaryChildren = nextProps.children; 20418 var fallbackChildFragment = updateSuspenseFallbackChildren(current, workInProgress, _nextPrimaryChildren, _nextFallbackChildren, renderLanes); 20419 var _primaryChildFragment2 = workInProgress.child; 20420 var prevOffscreenState = current.child.memoizedState; 20421 _primaryChildFragment2.memoizedState = prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); 20422 20423 _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree(current, renderLanes); 20424 workInProgress.memoizedState = SUSPENDED_MARKER; 20425 return fallbackChildFragment; 20426 } else { 20427 var _nextPrimaryChildren2 = nextProps.children; 20428 20429 var _primaryChildFragment3 = updateSuspensePrimaryChildren(current, workInProgress, _nextPrimaryChildren2, renderLanes); 20430 20431 workInProgress.memoizedState = null; 20432 return _primaryChildFragment3; 20433 } 20434 } 20435 } 20436 20437 function mountSuspensePrimaryChildren(workInProgress, primaryChildren, renderLanes) { 20438 var mode = workInProgress.mode; 20439 var primaryChildProps = { 20440 mode: 'visible', 20441 children: primaryChildren 20442 }; 20443 var primaryChildFragment = mountWorkInProgressOffscreenFiber(primaryChildProps, mode); 20444 primaryChildFragment.return = workInProgress; 20445 workInProgress.child = primaryChildFragment; 20446 return primaryChildFragment; 20447 } 20448 20449 function mountSuspenseFallbackChildren(workInProgress, primaryChildren, fallbackChildren, renderLanes) { 20450 var mode = workInProgress.mode; 20451 var progressedPrimaryFragment = workInProgress.child; 20452 var primaryChildProps = { 20453 mode: 'hidden', 20454 children: primaryChildren 20455 }; 20456 var primaryChildFragment; 20457 var fallbackChildFragment; 20458 20459 if ((mode & ConcurrentMode) === NoMode && progressedPrimaryFragment !== null) { 20460 // In legacy mode, we commit the primary tree as if it successfully 20461 // completed, even though it's in an inconsistent state. 20462 primaryChildFragment = progressedPrimaryFragment; 20463 primaryChildFragment.childLanes = NoLanes; 20464 primaryChildFragment.pendingProps = primaryChildProps; 20465 20466 if ( workInProgress.mode & ProfileMode) { 20467 // Reset the durations from the first pass so they aren't included in the 20468 // final amounts. This seems counterintuitive, since we're intentionally 20469 // not measuring part of the render phase, but this makes it match what we 20470 // do in Concurrent Mode. 20471 primaryChildFragment.actualDuration = 0; 20472 primaryChildFragment.actualStartTime = -1; 20473 primaryChildFragment.selfBaseDuration = 0; 20474 primaryChildFragment.treeBaseDuration = 0; 20475 } 20476 20477 fallbackChildFragment = createFiberFromFragment(fallbackChildren, mode, renderLanes, null); 20478 } else { 20479 primaryChildFragment = mountWorkInProgressOffscreenFiber(primaryChildProps, mode); 20480 fallbackChildFragment = createFiberFromFragment(fallbackChildren, mode, renderLanes, null); 20481 } 20482 20483 primaryChildFragment.return = workInProgress; 20484 fallbackChildFragment.return = workInProgress; 20485 primaryChildFragment.sibling = fallbackChildFragment; 20486 workInProgress.child = primaryChildFragment; 20487 return fallbackChildFragment; 20488 } 20489 20490 function mountWorkInProgressOffscreenFiber(offscreenProps, mode, renderLanes) { 20491 // The props argument to `createFiberFromOffscreen` is `any` typed, so we use 20492 // this wrapper function to constrain it. 20493 return createFiberFromOffscreen(offscreenProps, mode, NoLanes, null); 20494 } 20495 20496 function updateWorkInProgressOffscreenFiber(current, offscreenProps) { 20497 // The props argument to `createWorkInProgress` is `any` typed, so we use this 20498 // wrapper function to constrain it. 20499 return createWorkInProgress(current, offscreenProps); 20500 } 20501 20502 function updateSuspensePrimaryChildren(current, workInProgress, primaryChildren, renderLanes) { 20503 var currentPrimaryChildFragment = current.child; 20504 var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; 20505 var primaryChildFragment = updateWorkInProgressOffscreenFiber(currentPrimaryChildFragment, { 20506 mode: 'visible', 20507 children: primaryChildren 20508 }); 20509 20510 if ((workInProgress.mode & ConcurrentMode) === NoMode) { 20511 primaryChildFragment.lanes = renderLanes; 20512 } 20513 20514 primaryChildFragment.return = workInProgress; 20515 primaryChildFragment.sibling = null; 20516 20517 if (currentFallbackChildFragment !== null) { 20518 // Delete the fallback child fragment 20519 var deletions = workInProgress.deletions; 20520 20521 if (deletions === null) { 20522 workInProgress.deletions = [currentFallbackChildFragment]; 20523 workInProgress.flags |= ChildDeletion; 20524 } else { 20525 deletions.push(currentFallbackChildFragment); 20526 } 20527 } 20528 20529 workInProgress.child = primaryChildFragment; 20530 return primaryChildFragment; 20531 } 20532 20533 function updateSuspenseFallbackChildren(current, workInProgress, primaryChildren, fallbackChildren, renderLanes) { 20534 var mode = workInProgress.mode; 20535 var currentPrimaryChildFragment = current.child; 20536 var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; 20537 var primaryChildProps = { 20538 mode: 'hidden', 20539 children: primaryChildren 20540 }; 20541 var primaryChildFragment; 20542 20543 if ( // In legacy mode, we commit the primary tree as if it successfully 20544 // completed, even though it's in an inconsistent state. 20545 (mode & ConcurrentMode) === NoMode && // Make sure we're on the second pass, i.e. the primary child fragment was 20546 // already cloned. In legacy mode, the only case where this isn't true is 20547 // when DevTools forces us to display a fallback; we skip the first render 20548 // pass entirely and go straight to rendering the fallback. (In Concurrent 20549 // Mode, SuspenseList can also trigger this scenario, but this is a legacy- 20550 // only codepath.) 20551 workInProgress.child !== currentPrimaryChildFragment) { 20552 var progressedPrimaryFragment = workInProgress.child; 20553 primaryChildFragment = progressedPrimaryFragment; 20554 primaryChildFragment.childLanes = NoLanes; 20555 primaryChildFragment.pendingProps = primaryChildProps; 20556 20557 if ( workInProgress.mode & ProfileMode) { 20558 // Reset the durations from the first pass so they aren't included in the 20559 // final amounts. This seems counterintuitive, since we're intentionally 20560 // not measuring part of the render phase, but this makes it match what we 20561 // do in Concurrent Mode. 20562 primaryChildFragment.actualDuration = 0; 20563 primaryChildFragment.actualStartTime = -1; 20564 primaryChildFragment.selfBaseDuration = currentPrimaryChildFragment.selfBaseDuration; 20565 primaryChildFragment.treeBaseDuration = currentPrimaryChildFragment.treeBaseDuration; 20566 } // The fallback fiber was added as a deletion during the first pass. 20567 // However, since we're going to remain on the fallback, we no longer want 20568 // to delete it. 20569 20570 20571 workInProgress.deletions = null; 20572 } else { 20573 primaryChildFragment = updateWorkInProgressOffscreenFiber(currentPrimaryChildFragment, primaryChildProps); // Since we're reusing a current tree, we need to reuse the flags, too. 20574 // (We don't do this in legacy mode, because in legacy mode we don't re-use 20575 // the current tree; see previous branch.) 20576 20577 primaryChildFragment.subtreeFlags = currentPrimaryChildFragment.subtreeFlags & StaticMask; 20578 } 20579 20580 var fallbackChildFragment; 20581 20582 if (currentFallbackChildFragment !== null) { 20583 fallbackChildFragment = createWorkInProgress(currentFallbackChildFragment, fallbackChildren); 20584 } else { 20585 fallbackChildFragment = createFiberFromFragment(fallbackChildren, mode, renderLanes, null); // Needs a placement effect because the parent (the Suspense boundary) already 20586 // mounted but this is a new fiber. 20587 20588 fallbackChildFragment.flags |= Placement; 20589 } 20590 20591 fallbackChildFragment.return = workInProgress; 20592 primaryChildFragment.return = workInProgress; 20593 primaryChildFragment.sibling = fallbackChildFragment; 20594 workInProgress.child = primaryChildFragment; 20595 return fallbackChildFragment; 20596 } 20597 20598 function retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes, recoverableError) { 20599 // Falling back to client rendering. Because this has performance 20600 // implications, it's considered a recoverable error, even though the user 20601 // likely won't observe anything wrong with the UI. 20602 // 20603 // The error is passed in as an argument to enforce that every caller provide 20604 // a custom message, or explicitly opt out (currently the only path that opts 20605 // out is legacy mode; every concurrent path provides an error). 20606 if (recoverableError !== null) { 20607 queueHydrationError(recoverableError); 20608 } // This will add the old fiber to the deletion list 20609 20610 20611 reconcileChildFibers(workInProgress, current.child, null, renderLanes); // We're now not suspended nor dehydrated. 20612 20613 var nextProps = workInProgress.pendingProps; 20614 var primaryChildren = nextProps.children; 20615 var primaryChildFragment = mountSuspensePrimaryChildren(workInProgress, primaryChildren); // Needs a placement effect because the parent (the Suspense boundary) already 20616 // mounted but this is a new fiber. 20617 20618 primaryChildFragment.flags |= Placement; 20619 workInProgress.memoizedState = null; 20620 return primaryChildFragment; 20621 } 20622 20623 function mountSuspenseFallbackAfterRetryWithoutHydrating(current, workInProgress, primaryChildren, fallbackChildren, renderLanes) { 20624 var fiberMode = workInProgress.mode; 20625 var primaryChildProps = { 20626 mode: 'visible', 20627 children: primaryChildren 20628 }; 20629 var primaryChildFragment = mountWorkInProgressOffscreenFiber(primaryChildProps, fiberMode); 20630 var fallbackChildFragment = createFiberFromFragment(fallbackChildren, fiberMode, renderLanes, null); // Needs a placement effect because the parent (the Suspense 20631 // boundary) already mounted but this is a new fiber. 20632 20633 fallbackChildFragment.flags |= Placement; 20634 primaryChildFragment.return = workInProgress; 20635 fallbackChildFragment.return = workInProgress; 20636 primaryChildFragment.sibling = fallbackChildFragment; 20637 workInProgress.child = primaryChildFragment; 20638 20639 if ((workInProgress.mode & ConcurrentMode) !== NoMode) { 20640 // We will have dropped the effect list which contains the 20641 // deletion. We need to reconcile to delete the current child. 20642 reconcileChildFibers(workInProgress, current.child, null, renderLanes); 20643 } 20644 20645 return fallbackChildFragment; 20646 } 20647 20648 function mountDehydratedSuspenseComponent(workInProgress, suspenseInstance, renderLanes) { 20649 // During the first pass, we'll bail out and not drill into the children. 20650 // Instead, we'll leave the content in place and try to hydrate it later. 20651 if ((workInProgress.mode & ConcurrentMode) === NoMode) { 20652 { 20653 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.'); 20654 } 20655 20656 workInProgress.lanes = laneToLanes(SyncLane); 20657 } else if (isSuspenseInstanceFallback(suspenseInstance)) { 20658 // This is a client-only boundary. Since we won't get any content from the server 20659 // for this, we need to schedule that at a higher priority based on when it would 20660 // have timed out. In theory we could render it in this pass but it would have the 20661 // wrong priority associated with it and will prevent hydration of parent path. 20662 // Instead, we'll leave work left on it to render it in a separate commit. 20663 // TODO This time should be the time at which the server rendered response that is 20664 // a parent to this boundary was displayed. However, since we currently don't have 20665 // a protocol to transfer that time, we'll just estimate it by using the current 20666 // time. This will mean that Suspense timeouts are slightly shifted to later than 20667 // they should be. 20668 // Schedule a normal pri update to render this content. 20669 workInProgress.lanes = laneToLanes(DefaultHydrationLane); 20670 } else { 20671 // We'll continue hydrating the rest at offscreen priority since we'll already 20672 // be showing the right content coming from the server, it is no rush. 20673 workInProgress.lanes = laneToLanes(OffscreenLane); 20674 } 20675 20676 return null; 20677 } 20678 20679 function updateDehydratedSuspenseComponent(current, workInProgress, didSuspend, nextProps, suspenseInstance, suspenseState, renderLanes) { 20680 if (!didSuspend) { 20681 // This is the first render pass. Attempt to hydrate. 20682 // We should never be hydrating at this point because it is the first pass, 20683 // but after we've already committed once. 20684 warnIfHydrating(); 20685 20686 if ((workInProgress.mode & ConcurrentMode) === NoMode) { 20687 return retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes, // TODO: When we delete legacy mode, we should make this error argument 20688 // required — every concurrent mode path that causes hydration to 20689 // de-opt to client rendering should have an error message. 20690 null); 20691 } 20692 20693 if (isSuspenseInstanceFallback(suspenseInstance)) { 20694 // This boundary is in a permanent fallback state. In this case, we'll never 20695 // get an update and we'll never be able to hydrate the final content. Let's just try the 20696 // client side render instead. 20697 var digest, message, stack; 20698 20699 { 20700 var _getSuspenseInstanceF = getSuspenseInstanceFallbackErrorDetails(suspenseInstance); 20701 20702 digest = _getSuspenseInstanceF.digest; 20703 message = _getSuspenseInstanceF.message; 20704 stack = _getSuspenseInstanceF.stack; 20705 } 20706 20707 var error; 20708 20709 if (message) { 20710 // eslint-disable-next-line react-internal/prod-error-codes 20711 error = new Error(message); 20712 } else { 20713 error = new Error('The server could not finish this Suspense boundary, likely ' + 'due to an error during server rendering. Switched to ' + 'client rendering.'); 20714 } 20715 20716 var capturedValue = createCapturedValue(error, digest, stack); 20717 return retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes, capturedValue); 20718 } 20719 // any context has changed, we need to treat is as if the input might have changed. 20720 20721 20722 var hasContextChanged = includesSomeLane(renderLanes, current.childLanes); 20723 20724 if (didReceiveUpdate || hasContextChanged) { 20725 // This boundary has changed since the first render. This means that we are now unable to 20726 // hydrate it. We might still be able to hydrate it using a higher priority lane. 20727 var root = getWorkInProgressRoot(); 20728 20729 if (root !== null) { 20730 var attemptHydrationAtLane = getBumpedLaneForHydration(root, renderLanes); 20731 20732 if (attemptHydrationAtLane !== NoLane && attemptHydrationAtLane !== suspenseState.retryLane) { 20733 // Intentionally mutating since this render will get interrupted. This 20734 // is one of the very rare times where we mutate the current tree 20735 // during the render phase. 20736 suspenseState.retryLane = attemptHydrationAtLane; // TODO: Ideally this would inherit the event time of the current render 20737 20738 var eventTime = NoTimestamp; 20739 enqueueConcurrentRenderForLane(current, attemptHydrationAtLane); 20740 scheduleUpdateOnFiber(root, current, attemptHydrationAtLane, eventTime); 20741 } 20742 } // If we have scheduled higher pri work above, this will probably just abort the render 20743 // since we now have higher priority work, but in case it doesn't, we need to prepare to 20744 // render something, if we time out. Even if that requires us to delete everything and 20745 // skip hydration. 20746 // Delay having to do this as long as the suspense timeout allows us. 20747 20748 20749 renderDidSuspendDelayIfPossible(); 20750 20751 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.')); 20752 20753 return retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes, _capturedValue); 20754 } else if (isSuspenseInstancePending(suspenseInstance)) { 20755 // This component is still pending more data from the server, so we can't hydrate its 20756 // content. We treat it as if this component suspended itself. It might seem as if 20757 // we could just try to render it client-side instead. However, this will perform a 20758 // lot of unnecessary work and is unlikely to complete since it often will suspend 20759 // on missing data anyway. Additionally, the server might be able to render more 20760 // than we can on the client yet. In that case we'd end up with more fallback states 20761 // on the client than if we just leave it alone. If the server times out or errors 20762 // these should update this boundary to the permanent Fallback state instead. 20763 // Mark it as having captured (i.e. suspended). 20764 workInProgress.flags |= DidCapture; // Leave the child in place. I.e. the dehydrated fragment. 20765 20766 workInProgress.child = current.child; // Register a callback to retry this boundary once the server has sent the result. 20767 20768 var retry = retryDehydratedSuspenseBoundary.bind(null, current); 20769 registerSuspenseInstanceRetry(suspenseInstance, retry); 20770 return null; 20771 } else { 20772 // This is the first attempt. 20773 reenterHydrationStateFromDehydratedSuspenseInstance(workInProgress, suspenseInstance, suspenseState.treeContext); 20774 var primaryChildren = nextProps.children; 20775 var primaryChildFragment = mountSuspensePrimaryChildren(workInProgress, primaryChildren); // Mark the children as hydrating. This is a fast path to know whether this 20776 // tree is part of a hydrating tree. This is used to determine if a child 20777 // node has fully mounted yet, and for scheduling event replaying. 20778 // Conceptually this is similar to Placement in that a new subtree is 20779 // inserted into the React tree here. It just happens to not need DOM 20780 // mutations because it already exists. 20781 20782 primaryChildFragment.flags |= Hydrating; 20783 return primaryChildFragment; 20784 } 20785 } else { 20786 // This is the second render pass. We already attempted to hydrated, but 20787 // something either suspended or errored. 20788 if (workInProgress.flags & ForceClientRender) { 20789 // Something errored during hydration. Try again without hydrating. 20790 workInProgress.flags &= ~ForceClientRender; 20791 20792 var _capturedValue2 = createCapturedValue(new Error('There was an error while hydrating this Suspense boundary. ' + 'Switched to client rendering.')); 20793 20794 return retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes, _capturedValue2); 20795 } else if (workInProgress.memoizedState !== null) { 20796 // Something suspended and we should still be in dehydrated mode. 20797 // Leave the existing child in place. 20798 workInProgress.child = current.child; // The dehydrated completion pass expects this flag to be there 20799 // but the normal suspense pass doesn't. 20800 20801 workInProgress.flags |= DidCapture; 20802 return null; 20803 } else { 20804 // Suspended but we should no longer be in dehydrated mode. 20805 // Therefore we now have to render the fallback. 20806 var nextPrimaryChildren = nextProps.children; 20807 var nextFallbackChildren = nextProps.fallback; 20808 var fallbackChildFragment = mountSuspenseFallbackAfterRetryWithoutHydrating(current, workInProgress, nextPrimaryChildren, nextFallbackChildren, renderLanes); 20809 var _primaryChildFragment4 = workInProgress.child; 20810 _primaryChildFragment4.memoizedState = mountSuspenseOffscreenState(renderLanes); 20811 workInProgress.memoizedState = SUSPENDED_MARKER; 20812 return fallbackChildFragment; 20813 } 20814 } 20815 } 20816 20817 function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { 20818 fiber.lanes = mergeLanes(fiber.lanes, renderLanes); 20819 var alternate = fiber.alternate; 20820 20821 if (alternate !== null) { 20822 alternate.lanes = mergeLanes(alternate.lanes, renderLanes); 20823 } 20824 20825 scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); 20826 } 20827 20828 function propagateSuspenseContextChange(workInProgress, firstChild, renderLanes) { 20829 // Mark any Suspense boundaries with fallbacks as having work to do. 20830 // If they were previously forced into fallbacks, they may now be able 20831 // to unblock. 20832 var node = firstChild; 20833 20834 while (node !== null) { 20835 if (node.tag === SuspenseComponent) { 20836 var state = node.memoizedState; 20837 20838 if (state !== null) { 20839 scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); 20840 } 20841 } else if (node.tag === SuspenseListComponent) { 20842 // If the tail is hidden there might not be an Suspense boundaries 20843 // to schedule work on. In this case we have to schedule it on the 20844 // list itself. 20845 // We don't have to traverse to the children of the list since 20846 // the list will propagate the change when it rerenders. 20847 scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); 20848 } else if (node.child !== null) { 20849 node.child.return = node; 20850 node = node.child; 20851 continue; 20852 } 20853 20854 if (node === workInProgress) { 20855 return; 20856 } 20857 20858 while (node.sibling === null) { 20859 if (node.return === null || node.return === workInProgress) { 20860 return; 20861 } 20862 20863 node = node.return; 20864 } 20865 20866 node.sibling.return = node.return; 20867 node = node.sibling; 20868 } 20869 } 20870 20871 function findLastContentRow(firstChild) { 20872 // This is going to find the last row among these children that is already 20873 // showing content on the screen, as opposed to being in fallback state or 20874 // new. If a row has multiple Suspense boundaries, any of them being in the 20875 // fallback state, counts as the whole row being in a fallback state. 20876 // Note that the "rows" will be workInProgress, but any nested children 20877 // will still be current since we haven't rendered them yet. The mounted 20878 // order may not be the same as the new order. We use the new order. 20879 var row = firstChild; 20880 var lastContentRow = null; 20881 20882 while (row !== null) { 20883 var currentRow = row.alternate; // New rows can't be content rows. 20884 20885 if (currentRow !== null && findFirstSuspended(currentRow) === null) { 20886 lastContentRow = row; 20887 } 20888 20889 row = row.sibling; 20890 } 20891 20892 return lastContentRow; 20893 } 20894 20895 function validateRevealOrder(revealOrder) { 20896 { 20897 if (revealOrder !== undefined && revealOrder !== 'forwards' && revealOrder !== 'backwards' && revealOrder !== 'together' && !didWarnAboutRevealOrder[revealOrder]) { 20898 didWarnAboutRevealOrder[revealOrder] = true; 20899 20900 if (typeof revealOrder === 'string') { 20901 switch (revealOrder.toLowerCase()) { 20902 case 'together': 20903 case 'forwards': 20904 case 'backwards': 20905 { 20906 error('"%s" is not a valid value for revealOrder on <SuspenseList />. ' + 'Use lowercase "%s" instead.', revealOrder, revealOrder.toLowerCase()); 20907 20908 break; 20909 } 20910 20911 case 'forward': 20912 case 'backward': 20913 { 20914 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()); 20915 20916 break; 20917 } 20918 20919 default: 20920 error('"%s" is not a supported revealOrder on <SuspenseList />. ' + 'Did you mean "together", "forwards" or "backwards"?', revealOrder); 20921 20922 break; 20923 } 20924 } else { 20925 error('%s is not a supported value for revealOrder on <SuspenseList />. ' + 'Did you mean "together", "forwards" or "backwards"?', revealOrder); 20926 } 20927 } 20928 } 20929 } 20930 20931 function validateTailOptions(tailMode, revealOrder) { 20932 { 20933 if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) { 20934 if (tailMode !== 'collapsed' && tailMode !== 'hidden') { 20935 didWarnAboutTailOptions[tailMode] = true; 20936 20937 error('"%s" is not a supported value for tail on <SuspenseList />. ' + 'Did you mean "collapsed" or "hidden"?', tailMode); 20938 } else if (revealOrder !== 'forwards' && revealOrder !== 'backwards') { 20939 didWarnAboutTailOptions[tailMode] = true; 20940 20941 error('<SuspenseList tail="%s" /> is only valid if revealOrder is ' + '"forwards" or "backwards". ' + 'Did you mean to specify revealOrder="forwards"?', tailMode); 20942 } 20943 } 20944 } 20945 } 20946 20947 function validateSuspenseListNestedChild(childSlot, index) { 20948 { 20949 var isAnArray = isArray(childSlot); 20950 var isIterable = !isAnArray && typeof getIteratorFn(childSlot) === 'function'; 20951 20952 if (isAnArray || isIterable) { 20953 var type = isAnArray ? 'array' : 'iterable'; 20954 20955 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); 20956 20957 return false; 20958 } 20959 } 20960 20961 return true; 20962 } 20963 20964 function validateSuspenseListChildren(children, revealOrder) { 20965 { 20966 if ((revealOrder === 'forwards' || revealOrder === 'backwards') && children !== undefined && children !== null && children !== false) { 20967 if (isArray(children)) { 20968 for (var i = 0; i < children.length; i++) { 20969 if (!validateSuspenseListNestedChild(children[i], i)) { 20970 return; 20971 } 20972 } 20973 } else { 20974 var iteratorFn = getIteratorFn(children); 20975 20976 if (typeof iteratorFn === 'function') { 20977 var childrenIterator = iteratorFn.call(children); 20978 20979 if (childrenIterator) { 20980 var step = childrenIterator.next(); 20981 var _i = 0; 20982 20983 for (; !step.done; step = childrenIterator.next()) { 20984 if (!validateSuspenseListNestedChild(step.value, _i)) { 20985 return; 20986 } 20987 20988 _i++; 20989 } 20990 } 20991 } else { 20992 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); 20993 } 20994 } 20995 } 20996 } 20997 } 20998 20999 function initSuspenseListRenderState(workInProgress, isBackwards, tail, lastContentRow, tailMode) { 21000 var renderState = workInProgress.memoizedState; 21001 21002 if (renderState === null) { 21003 workInProgress.memoizedState = { 21004 isBackwards: isBackwards, 21005 rendering: null, 21006 renderingStartTime: 0, 21007 last: lastContentRow, 21008 tail: tail, 21009 tailMode: tailMode 21010 }; 21011 } else { 21012 // We can reuse the existing object from previous renders. 21013 renderState.isBackwards = isBackwards; 21014 renderState.rendering = null; 21015 renderState.renderingStartTime = 0; 21016 renderState.last = lastContentRow; 21017 renderState.tail = tail; 21018 renderState.tailMode = tailMode; 21019 } 21020 } // This can end up rendering this component multiple passes. 21021 // The first pass splits the children fibers into two sets. A head and tail. 21022 // We first render the head. If anything is in fallback state, we do another 21023 // pass through beginWork to rerender all children (including the tail) with 21024 // the force suspend context. If the first render didn't have anything in 21025 // in fallback state. Then we render each row in the tail one-by-one. 21026 // That happens in the completeWork phase without going back to beginWork. 21027 21028 21029 function updateSuspenseListComponent(current, workInProgress, renderLanes) { 21030 var nextProps = workInProgress.pendingProps; 21031 var revealOrder = nextProps.revealOrder; 21032 var tailMode = nextProps.tail; 21033 var newChildren = nextProps.children; 21034 validateRevealOrder(revealOrder); 21035 validateTailOptions(tailMode, revealOrder); 21036 validateSuspenseListChildren(newChildren, revealOrder); 21037 reconcileChildren(current, workInProgress, newChildren, renderLanes); 21038 var suspenseContext = suspenseStackCursor.current; 21039 var shouldForceFallback = hasSuspenseContext(suspenseContext, ForceSuspenseFallback); 21040 21041 if (shouldForceFallback) { 21042 suspenseContext = setShallowSuspenseContext(suspenseContext, ForceSuspenseFallback); 21043 workInProgress.flags |= DidCapture; 21044 } else { 21045 var didSuspendBefore = current !== null && (current.flags & DidCapture) !== NoFlags; 21046 21047 if (didSuspendBefore) { 21048 // If we previously forced a fallback, we need to schedule work 21049 // on any nested boundaries to let them know to try to render 21050 // again. This is the same as context updating. 21051 propagateSuspenseContextChange(workInProgress, workInProgress.child, renderLanes); 21052 } 21053 21054 suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); 21055 } 21056 21057 pushSuspenseContext(workInProgress, suspenseContext); 21058 21059 if ((workInProgress.mode & ConcurrentMode) === NoMode) { 21060 // In legacy mode, SuspenseList doesn't work so we just 21061 // use make it a noop by treating it as the default revealOrder. 21062 workInProgress.memoizedState = null; 21063 } else { 21064 switch (revealOrder) { 21065 case 'forwards': 21066 { 21067 var lastContentRow = findLastContentRow(workInProgress.child); 21068 var tail; 21069 21070 if (lastContentRow === null) { 21071 // The whole list is part of the tail. 21072 // TODO: We could fast path by just rendering the tail now. 21073 tail = workInProgress.child; 21074 workInProgress.child = null; 21075 } else { 21076 // Disconnect the tail rows after the content row. 21077 // We're going to render them separately later. 21078 tail = lastContentRow.sibling; 21079 lastContentRow.sibling = null; 21080 } 21081 21082 initSuspenseListRenderState(workInProgress, false, // isBackwards 21083 tail, lastContentRow, tailMode); 21084 break; 21085 } 21086 21087 case 'backwards': 21088 { 21089 // We're going to find the first row that has existing content. 21090 // At the same time we're going to reverse the list of everything 21091 // we pass in the meantime. That's going to be our tail in reverse 21092 // order. 21093 var _tail = null; 21094 var row = workInProgress.child; 21095 workInProgress.child = null; 21096 21097 while (row !== null) { 21098 var currentRow = row.alternate; // New rows can't be content rows. 21099 21100 if (currentRow !== null && findFirstSuspended(currentRow) === null) { 21101 // This is the beginning of the main content. 21102 workInProgress.child = row; 21103 break; 21104 } 21105 21106 var nextRow = row.sibling; 21107 row.sibling = _tail; 21108 _tail = row; 21109 row = nextRow; 21110 } // TODO: If workInProgress.child is null, we can continue on the tail immediately. 21111 21112 21113 initSuspenseListRenderState(workInProgress, true, // isBackwards 21114 _tail, null, // last 21115 tailMode); 21116 break; 21117 } 21118 21119 case 'together': 21120 { 21121 initSuspenseListRenderState(workInProgress, false, // isBackwards 21122 null, // tail 21123 null, // last 21124 undefined); 21125 break; 21126 } 21127 21128 default: 21129 { 21130 // The default reveal order is the same as not having 21131 // a boundary. 21132 workInProgress.memoizedState = null; 21133 } 21134 } 21135 } 21136 21137 return workInProgress.child; 21138 } 21139 21140 function updatePortalComponent(current, workInProgress, renderLanes) { 21141 pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); 21142 var nextChildren = workInProgress.pendingProps; 21143 21144 if (current === null) { 21145 // Portals are special because we don't append the children during mount 21146 // but at commit. Therefore we need to track insertions which the normal 21147 // flow doesn't do during mount. This doesn't happen at the root because 21148 // the root always starts with a "current" with a null child. 21149 // TODO: Consider unifying this with how the root works. 21150 workInProgress.child = reconcileChildFibers(workInProgress, null, nextChildren, renderLanes); 21151 } else { 21152 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 21153 } 21154 21155 return workInProgress.child; 21156 } 21157 21158 var hasWarnedAboutUsingNoValuePropOnContextProvider = false; 21159 21160 function updateContextProvider(current, workInProgress, renderLanes) { 21161 var providerType = workInProgress.type; 21162 var context = providerType._context; 21163 var newProps = workInProgress.pendingProps; 21164 var oldProps = workInProgress.memoizedProps; 21165 var newValue = newProps.value; 21166 21167 { 21168 if (!('value' in newProps)) { 21169 if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { 21170 hasWarnedAboutUsingNoValuePropOnContextProvider = true; 21171 21172 error('The `value` prop is required for the `<Context.Provider>`. Did you misspell it or forget to pass it?'); 21173 } 21174 } 21175 21176 var providerPropTypes = workInProgress.type.propTypes; 21177 21178 if (providerPropTypes) { 21179 checkPropTypes(providerPropTypes, newProps, 'prop', 'Context.Provider'); 21180 } 21181 } 21182 21183 pushProvider(workInProgress, context, newValue); 21184 21185 { 21186 if (oldProps !== null) { 21187 var oldValue = oldProps.value; 21188 21189 if (objectIs(oldValue, newValue)) { 21190 // No change. Bailout early if children are the same. 21191 if (oldProps.children === newProps.children && !hasContextChanged()) { 21192 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 21193 } 21194 } else { 21195 // The context value changed. Search for matching consumers and schedule 21196 // them to update. 21197 propagateContextChange(workInProgress, context, renderLanes); 21198 } 21199 } 21200 } 21201 21202 var newChildren = newProps.children; 21203 reconcileChildren(current, workInProgress, newChildren, renderLanes); 21204 return workInProgress.child; 21205 } 21206 21207 var hasWarnedAboutUsingContextAsConsumer = false; 21208 21209 function updateContextConsumer(current, workInProgress, renderLanes) { 21210 var context = workInProgress.type; // The logic below for Context differs depending on PROD or DEV mode. In 21211 // DEV mode, we create a separate object for Context.Consumer that acts 21212 // like a proxy to Context. This proxy object adds unnecessary code in PROD 21213 // so we use the old behaviour (Context.Consumer references Context) to 21214 // reduce size and overhead. The separate object references context via 21215 // a property called "_context", which also gives us the ability to check 21216 // in DEV mode if this property exists or not and warn if it does not. 21217 21218 { 21219 if (context._context === undefined) { 21220 // This may be because it's a Context (rather than a Consumer). 21221 // Or it may be because it's older React where they're the same thing. 21222 // We only want to warn if we're sure it's a new React. 21223 if (context !== context.Consumer) { 21224 if (!hasWarnedAboutUsingContextAsConsumer) { 21225 hasWarnedAboutUsingContextAsConsumer = true; 21226 21227 error('Rendering <Context> directly is not supported and will be removed in ' + 'a future major release. Did you mean to render <Context.Consumer> instead?'); 21228 } 21229 } 21230 } else { 21231 context = context._context; 21232 } 21233 } 21234 21235 var newProps = workInProgress.pendingProps; 21236 var render = newProps.children; 21237 21238 { 21239 if (typeof render !== 'function') { 21240 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.'); 21241 } 21242 } 21243 21244 prepareToReadContext(workInProgress, renderLanes); 21245 var newValue = readContext(context); 21246 21247 { 21248 markComponentRenderStarted(workInProgress); 21249 } 21250 21251 var newChildren; 21252 21253 { 21254 ReactCurrentOwner$1.current = workInProgress; 21255 setIsRendering(true); 21256 newChildren = render(newValue); 21257 setIsRendering(false); 21258 } 21259 21260 { 21261 markComponentRenderStopped(); 21262 } // React DevTools reads this flag. 21263 21264 21265 workInProgress.flags |= PerformedWork; 21266 reconcileChildren(current, workInProgress, newChildren, renderLanes); 21267 return workInProgress.child; 21268 } 21269 21270 function markWorkInProgressReceivedUpdate() { 21271 didReceiveUpdate = true; 21272 } 21273 21274 function resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress) { 21275 if ((workInProgress.mode & ConcurrentMode) === NoMode) { 21276 if (current !== null) { 21277 // A lazy component only mounts if it suspended inside a non- 21278 // concurrent tree, in an inconsistent state. We want to treat it like 21279 // a new mount, even though an empty version of it already committed. 21280 // Disconnect the alternate pointers. 21281 current.alternate = null; 21282 workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect 21283 21284 workInProgress.flags |= Placement; 21285 } 21286 } 21287 } 21288 21289 function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { 21290 if (current !== null) { 21291 // Reuse previous dependencies 21292 workInProgress.dependencies = current.dependencies; 21293 } 21294 21295 { 21296 // Don't update "base" render times for bailouts. 21297 stopProfilerTimerIfRunning(); 21298 } 21299 21300 markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. 21301 21302 if (!includesSomeLane(renderLanes, workInProgress.childLanes)) { 21303 // The children don't have any work either. We can skip them. 21304 // TODO: Once we add back resuming, we should check if the children are 21305 // a work-in-progress set. If so, we need to transfer their effects. 21306 { 21307 return null; 21308 } 21309 } // This fiber doesn't have work, but its subtree does. Clone the child 21310 // fibers and continue. 21311 21312 21313 cloneChildFibers(current, workInProgress); 21314 return workInProgress.child; 21315 } 21316 21317 function remountFiber(current, oldWorkInProgress, newWorkInProgress) { 21318 { 21319 var returnFiber = oldWorkInProgress.return; 21320 21321 if (returnFiber === null) { 21322 // eslint-disable-next-line react-internal/prod-error-codes 21323 throw new Error('Cannot swap the root fiber.'); 21324 } // Disconnect from the old current. 21325 // It will get deleted. 21326 21327 21328 current.alternate = null; 21329 oldWorkInProgress.alternate = null; // Connect to the new tree. 21330 21331 newWorkInProgress.index = oldWorkInProgress.index; 21332 newWorkInProgress.sibling = oldWorkInProgress.sibling; 21333 newWorkInProgress.return = oldWorkInProgress.return; 21334 newWorkInProgress.ref = oldWorkInProgress.ref; // Replace the child/sibling pointers above it. 21335 21336 if (oldWorkInProgress === returnFiber.child) { 21337 returnFiber.child = newWorkInProgress; 21338 } else { 21339 var prevSibling = returnFiber.child; 21340 21341 if (prevSibling === null) { 21342 // eslint-disable-next-line react-internal/prod-error-codes 21343 throw new Error('Expected parent to have a child.'); 21344 } 21345 21346 while (prevSibling.sibling !== oldWorkInProgress) { 21347 prevSibling = prevSibling.sibling; 21348 21349 if (prevSibling === null) { 21350 // eslint-disable-next-line react-internal/prod-error-codes 21351 throw new Error('Expected to find the previous sibling.'); 21352 } 21353 } 21354 21355 prevSibling.sibling = newWorkInProgress; 21356 } // Delete the old fiber and place the new one. 21357 // Since the old fiber is disconnected, we have to schedule it manually. 21358 21359 21360 var deletions = returnFiber.deletions; 21361 21362 if (deletions === null) { 21363 returnFiber.deletions = [current]; 21364 returnFiber.flags |= ChildDeletion; 21365 } else { 21366 deletions.push(current); 21367 } 21368 21369 newWorkInProgress.flags |= Placement; // Restart work from the new fiber. 21370 21371 return newWorkInProgress; 21372 } 21373 } 21374 21375 function checkScheduledUpdateOrContext(current, renderLanes) { 21376 // Before performing an early bailout, we must check if there are pending 21377 // updates or context. 21378 var updateLanes = current.lanes; 21379 21380 if (includesSomeLane(updateLanes, renderLanes)) { 21381 return true; 21382 } // No pending update, but because context is propagated lazily, we need 21383 21384 return false; 21385 } 21386 21387 function attemptEarlyBailoutIfNoScheduledUpdate(current, workInProgress, renderLanes) { 21388 // This fiber does not have any pending work. Bailout without entering 21389 // the begin phase. There's still some bookkeeping we that needs to be done 21390 // in this optimized path, mostly pushing stuff onto the stack. 21391 switch (workInProgress.tag) { 21392 case HostRoot: 21393 pushHostRootContext(workInProgress); 21394 var root = workInProgress.stateNode; 21395 21396 resetHydrationState(); 21397 break; 21398 21399 case HostComponent: 21400 pushHostContext(workInProgress); 21401 break; 21402 21403 case ClassComponent: 21404 { 21405 var Component = workInProgress.type; 21406 21407 if (isContextProvider(Component)) { 21408 pushContextProvider(workInProgress); 21409 } 21410 21411 break; 21412 } 21413 21414 case HostPortal: 21415 pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); 21416 break; 21417 21418 case ContextProvider: 21419 { 21420 var newValue = workInProgress.memoizedProps.value; 21421 var context = workInProgress.type._context; 21422 pushProvider(workInProgress, context, newValue); 21423 break; 21424 } 21425 21426 case Profiler: 21427 { 21428 // Profiler should only call onRender when one of its descendants actually rendered. 21429 var hasChildWork = includesSomeLane(renderLanes, workInProgress.childLanes); 21430 21431 if (hasChildWork) { 21432 workInProgress.flags |= Update; 21433 } 21434 21435 { 21436 // Reset effect durations for the next eventual effect phase. 21437 // These are reset during render to allow the DevTools commit hook a chance to read them, 21438 var stateNode = workInProgress.stateNode; 21439 stateNode.effectDuration = 0; 21440 stateNode.passiveEffectDuration = 0; 21441 } 21442 } 21443 21444 break; 21445 21446 case SuspenseComponent: 21447 { 21448 var state = workInProgress.memoizedState; 21449 21450 if (state !== null) { 21451 if (state.dehydrated !== null) { 21452 pushSuspenseContext(workInProgress, setDefaultShallowSuspenseContext(suspenseStackCursor.current)); // We know that this component will suspend again because if it has 21453 // been unsuspended it has committed as a resolved Suspense component. 21454 // If it needs to be retried, it should have work scheduled on it. 21455 21456 workInProgress.flags |= DidCapture; // We should never render the children of a dehydrated boundary until we 21457 // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork. 21458 21459 return null; 21460 } // If this boundary is currently timed out, we need to decide 21461 // whether to retry the primary children, or to skip over it and 21462 // go straight to the fallback. Check the priority of the primary 21463 // child fragment. 21464 21465 21466 var primaryChildFragment = workInProgress.child; 21467 var primaryChildLanes = primaryChildFragment.childLanes; 21468 21469 if (includesSomeLane(renderLanes, primaryChildLanes)) { 21470 // The primary children have pending work. Use the normal path 21471 // to attempt to render the primary children again. 21472 return updateSuspenseComponent(current, workInProgress, renderLanes); 21473 } else { 21474 // The primary child fragment does not have pending work marked 21475 // on it 21476 pushSuspenseContext(workInProgress, setDefaultShallowSuspenseContext(suspenseStackCursor.current)); // The primary children do not have pending work with sufficient 21477 // priority. Bailout. 21478 21479 var child = bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 21480 21481 if (child !== null) { 21482 // The fallback children have pending work. Skip over the 21483 // primary children and work on the fallback. 21484 return child.sibling; 21485 } else { 21486 // Note: We can return `null` here because we already checked 21487 // whether there were nested context consumers, via the call to 21488 // `bailoutOnAlreadyFinishedWork` above. 21489 return null; 21490 } 21491 } 21492 } else { 21493 pushSuspenseContext(workInProgress, setDefaultShallowSuspenseContext(suspenseStackCursor.current)); 21494 } 21495 21496 break; 21497 } 21498 21499 case SuspenseListComponent: 21500 { 21501 var didSuspendBefore = (current.flags & DidCapture) !== NoFlags; 21502 21503 var _hasChildWork = includesSomeLane(renderLanes, workInProgress.childLanes); 21504 21505 if (didSuspendBefore) { 21506 if (_hasChildWork) { 21507 // If something was in fallback state last time, and we have all the 21508 // same children then we're still in progressive loading state. 21509 // Something might get unblocked by state updates or retries in the 21510 // tree which will affect the tail. So we need to use the normal 21511 // path to compute the correct tail. 21512 return updateSuspenseListComponent(current, workInProgress, renderLanes); 21513 } // If none of the children had any work, that means that none of 21514 // them got retried so they'll still be blocked in the same way 21515 // as before. We can fast bail out. 21516 21517 21518 workInProgress.flags |= DidCapture; 21519 } // If nothing suspended before and we're rendering the same children, 21520 // then the tail doesn't matter. Anything new that suspends will work 21521 // in the "together" mode, so we can continue from the state we had. 21522 21523 21524 var renderState = workInProgress.memoizedState; 21525 21526 if (renderState !== null) { 21527 // Reset to the "together" mode in case we've started a different 21528 // update in the past but didn't complete it. 21529 renderState.rendering = null; 21530 renderState.tail = null; 21531 renderState.lastEffect = null; 21532 } 21533 21534 pushSuspenseContext(workInProgress, suspenseStackCursor.current); 21535 21536 if (_hasChildWork) { 21537 break; 21538 } else { 21539 // If none of the children had any work, that means that none of 21540 // them got retried so they'll still be blocked in the same way 21541 // as before. We can fast bail out. 21542 return null; 21543 } 21544 } 21545 21546 case OffscreenComponent: 21547 case LegacyHiddenComponent: 21548 { 21549 // Need to check if the tree still needs to be deferred. This is 21550 // almost identical to the logic used in the normal update path, 21551 // so we'll just enter that. The only difference is we'll bail out 21552 // at the next level instead of this one, because the child props 21553 // have not changed. Which is fine. 21554 // TODO: Probably should refactor `beginWork` to split the bailout 21555 // path from the normal path. I'm tempted to do a labeled break here 21556 // but I won't :) 21557 workInProgress.lanes = NoLanes; 21558 return updateOffscreenComponent(current, workInProgress, renderLanes); 21559 } 21560 } 21561 21562 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 21563 } 21564 21565 function beginWork(current, workInProgress, renderLanes) { 21566 { 21567 if (workInProgress._debugNeedsRemount && current !== null) { 21568 // This will restart the begin phase with a new fiber. 21569 return remountFiber(current, workInProgress, createFiberFromTypeAndProps(workInProgress.type, workInProgress.key, workInProgress.pendingProps, workInProgress._debugOwner || null, workInProgress.mode, workInProgress.lanes)); 21570 } 21571 } 21572 21573 if (current !== null) { 21574 var oldProps = current.memoizedProps; 21575 var newProps = workInProgress.pendingProps; 21576 21577 if (oldProps !== newProps || hasContextChanged() || ( // Force a re-render if the implementation changed due to hot reload: 21578 workInProgress.type !== current.type )) { 21579 // If props or context changed, mark the fiber as having performed work. 21580 // This may be unset if the props are determined to be equal later (memo). 21581 didReceiveUpdate = true; 21582 } else { 21583 // Neither props nor legacy context changes. Check if there's a pending 21584 // update or context change. 21585 var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext(current, renderLanes); 21586 21587 if (!hasScheduledUpdateOrContext && // If this is the second pass of an error or suspense boundary, there 21588 // may not be work scheduled on `current`, so we check for this flag. 21589 (workInProgress.flags & DidCapture) === NoFlags) { 21590 // No pending updates or context. Bail out now. 21591 didReceiveUpdate = false; 21592 return attemptEarlyBailoutIfNoScheduledUpdate(current, workInProgress, renderLanes); 21593 } 21594 21595 if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { 21596 // This is a special case that only exists for legacy mode. 21597 // See https://github.com/facebook/react/pull/19216. 21598 didReceiveUpdate = true; 21599 } else { 21600 // An update was scheduled on this fiber, but there are no new props 21601 // nor legacy context. Set this to false. If an update queue or context 21602 // consumer produces a changed value, it will set this to true. Otherwise, 21603 // the component will assume the children have not changed and bail out. 21604 didReceiveUpdate = false; 21605 } 21606 } 21607 } else { 21608 didReceiveUpdate = false; 21609 21610 if (getIsHydrating() && isForkedChild(workInProgress)) { 21611 // Check if this child belongs to a list of muliple children in 21612 // its parent. 21613 // 21614 // In a true multi-threaded implementation, we would render children on 21615 // parallel threads. This would represent the beginning of a new render 21616 // thread for this subtree. 21617 // 21618 // We only use this for id generation during hydration, which is why the 21619 // logic is located in this special branch. 21620 var slotIndex = workInProgress.index; 21621 var numberOfForks = getForksAtLevel(); 21622 pushTreeId(workInProgress, numberOfForks, slotIndex); 21623 } 21624 } // Before entering the begin phase, clear pending update priority. 21625 // TODO: This assumes that we're about to evaluate the component and process 21626 // the update queue. However, there's an exception: SimpleMemoComponent 21627 // sometimes bails out later in the begin phase. This indicates that we should 21628 // move this assignment out of the common path and into each branch. 21629 21630 21631 workInProgress.lanes = NoLanes; 21632 21633 switch (workInProgress.tag) { 21634 case IndeterminateComponent: 21635 { 21636 return mountIndeterminateComponent(current, workInProgress, workInProgress.type, renderLanes); 21637 } 21638 21639 case LazyComponent: 21640 { 21641 var elementType = workInProgress.elementType; 21642 return mountLazyComponent(current, workInProgress, elementType, renderLanes); 21643 } 21644 21645 case FunctionComponent: 21646 { 21647 var Component = workInProgress.type; 21648 var unresolvedProps = workInProgress.pendingProps; 21649 var resolvedProps = workInProgress.elementType === Component ? unresolvedProps : resolveDefaultProps(Component, unresolvedProps); 21650 return updateFunctionComponent(current, workInProgress, Component, resolvedProps, renderLanes); 21651 } 21652 21653 case ClassComponent: 21654 { 21655 var _Component = workInProgress.type; 21656 var _unresolvedProps = workInProgress.pendingProps; 21657 21658 var _resolvedProps = workInProgress.elementType === _Component ? _unresolvedProps : resolveDefaultProps(_Component, _unresolvedProps); 21659 21660 return updateClassComponent(current, workInProgress, _Component, _resolvedProps, renderLanes); 21661 } 21662 21663 case HostRoot: 21664 return updateHostRoot(current, workInProgress, renderLanes); 21665 21666 case HostComponent: 21667 return updateHostComponent(current, workInProgress, renderLanes); 21668 21669 case HostText: 21670 return updateHostText(current, workInProgress); 21671 21672 case SuspenseComponent: 21673 return updateSuspenseComponent(current, workInProgress, renderLanes); 21674 21675 case HostPortal: 21676 return updatePortalComponent(current, workInProgress, renderLanes); 21677 21678 case ForwardRef: 21679 { 21680 var type = workInProgress.type; 21681 var _unresolvedProps2 = workInProgress.pendingProps; 21682 21683 var _resolvedProps2 = workInProgress.elementType === type ? _unresolvedProps2 : resolveDefaultProps(type, _unresolvedProps2); 21684 21685 return updateForwardRef(current, workInProgress, type, _resolvedProps2, renderLanes); 21686 } 21687 21688 case Fragment: 21689 return updateFragment(current, workInProgress, renderLanes); 21690 21691 case Mode: 21692 return updateMode(current, workInProgress, renderLanes); 21693 21694 case Profiler: 21695 return updateProfiler(current, workInProgress, renderLanes); 21696 21697 case ContextProvider: 21698 return updateContextProvider(current, workInProgress, renderLanes); 21699 21700 case ContextConsumer: 21701 return updateContextConsumer(current, workInProgress, renderLanes); 21702 21703 case MemoComponent: 21704 { 21705 var _type2 = workInProgress.type; 21706 var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. 21707 21708 var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); 21709 21710 { 21711 if (workInProgress.type !== workInProgress.elementType) { 21712 var outerPropTypes = _type2.propTypes; 21713 21714 if (outerPropTypes) { 21715 checkPropTypes(outerPropTypes, _resolvedProps3, // Resolved for outer only 21716 'prop', getComponentNameFromType(_type2)); 21717 } 21718 } 21719 } 21720 21721 _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); 21722 return updateMemoComponent(current, workInProgress, _type2, _resolvedProps3, renderLanes); 21723 } 21724 21725 case SimpleMemoComponent: 21726 { 21727 return updateSimpleMemoComponent(current, workInProgress, workInProgress.type, workInProgress.pendingProps, renderLanes); 21728 } 21729 21730 case IncompleteClassComponent: 21731 { 21732 var _Component2 = workInProgress.type; 21733 var _unresolvedProps4 = workInProgress.pendingProps; 21734 21735 var _resolvedProps4 = workInProgress.elementType === _Component2 ? _unresolvedProps4 : resolveDefaultProps(_Component2, _unresolvedProps4); 21736 21737 return mountIncompleteClassComponent(current, workInProgress, _Component2, _resolvedProps4, renderLanes); 21738 } 21739 21740 case SuspenseListComponent: 21741 { 21742 return updateSuspenseListComponent(current, workInProgress, renderLanes); 21743 } 21744 21745 case ScopeComponent: 21746 { 21747 21748 break; 21749 } 21750 21751 case OffscreenComponent: 21752 { 21753 return updateOffscreenComponent(current, workInProgress, renderLanes); 21754 } 21755 } 21756 21757 throw new Error("Unknown unit of work tag (" + workInProgress.tag + "). This error is likely caused by a bug in " + 'React. Please file an issue.'); 21758 } 21759 21760 function markUpdate(workInProgress) { 21761 // Tag the fiber with an update effect. This turns a Placement into 21762 // a PlacementAndUpdate. 21763 workInProgress.flags |= Update; 21764 } 21765 21766 function markRef$1(workInProgress) { 21767 workInProgress.flags |= Ref; 21768 21769 { 21770 workInProgress.flags |= RefStatic; 21771 } 21772 } 21773 21774 var appendAllChildren; 21775 var updateHostContainer; 21776 var updateHostComponent$1; 21777 var updateHostText$1; 21778 21779 { 21780 // Mutation mode 21781 appendAllChildren = function (parent, workInProgress, needsVisibilityToggle, isHidden) { 21782 // We only have the top Fiber that was created but we need recurse down its 21783 // children to find all the terminal nodes. 21784 var node = workInProgress.child; 21785 21786 while (node !== null) { 21787 if (node.tag === HostComponent || node.tag === HostText) { 21788 appendInitialChild(parent, node.stateNode); 21789 } else if (node.tag === HostPortal) ; else if (node.child !== null) { 21790 node.child.return = node; 21791 node = node.child; 21792 continue; 21793 } 21794 21795 if (node === workInProgress) { 21796 return; 21797 } 21798 21799 while (node.sibling === null) { 21800 if (node.return === null || node.return === workInProgress) { 21801 return; 21802 } 21803 21804 node = node.return; 21805 } 21806 21807 node.sibling.return = node.return; 21808 node = node.sibling; 21809 } 21810 }; 21811 21812 updateHostContainer = function (current, workInProgress) {// Noop 21813 }; 21814 21815 updateHostComponent$1 = function (current, workInProgress, type, newProps, rootContainerInstance) { 21816 // If we have an alternate, that means this is an update and we need to 21817 // schedule a side-effect to do the updates. 21818 var oldProps = current.memoizedProps; 21819 21820 if (oldProps === newProps) { 21821 // In mutation mode, this is sufficient for a bailout because 21822 // we won't touch this node even if children changed. 21823 return; 21824 } // If we get updated because one of our children updated, we don't 21825 // have newProps so we'll have to reuse them. 21826 // TODO: Split the update API as separate for the props vs. children. 21827 // Even better would be if children weren't special cased at all tho. 21828 21829 21830 var instance = workInProgress.stateNode; 21831 var currentHostContext = getHostContext(); // TODO: Experiencing an error where oldProps is null. Suggests a host 21832 // component is hitting the resume path. Figure out why. Possibly 21833 // related to `hidden`. 21834 21835 var updatePayload = prepareUpdate(instance, type, oldProps, newProps, rootContainerInstance, currentHostContext); // TODO: Type this specific to this type of component. 21836 21837 workInProgress.updateQueue = updatePayload; // If the update payload indicates that there is a change or if there 21838 // is a new ref we mark this as an update. All the work is done in commitWork. 21839 21840 if (updatePayload) { 21841 markUpdate(workInProgress); 21842 } 21843 }; 21844 21845 updateHostText$1 = function (current, workInProgress, oldText, newText) { 21846 // If the text differs, mark it as an update. All the work in done in commitWork. 21847 if (oldText !== newText) { 21848 markUpdate(workInProgress); 21849 } 21850 }; 21851 } 21852 21853 function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { 21854 if (getIsHydrating()) { 21855 // If we're hydrating, we should consume as many items as we can 21856 // so we don't leave any behind. 21857 return; 21858 } 21859 21860 switch (renderState.tailMode) { 21861 case 'hidden': 21862 { 21863 // Any insertions at the end of the tail list after this point 21864 // should be invisible. If there are already mounted boundaries 21865 // anything before them are not considered for collapsing. 21866 // Therefore we need to go through the whole tail to find if 21867 // there are any. 21868 var tailNode = renderState.tail; 21869 var lastTailNode = null; 21870 21871 while (tailNode !== null) { 21872 if (tailNode.alternate !== null) { 21873 lastTailNode = tailNode; 21874 } 21875 21876 tailNode = tailNode.sibling; 21877 } // Next we're simply going to delete all insertions after the 21878 // last rendered item. 21879 21880 21881 if (lastTailNode === null) { 21882 // All remaining items in the tail are insertions. 21883 renderState.tail = null; 21884 } else { 21885 // Detach the insertion after the last node that was already 21886 // inserted. 21887 lastTailNode.sibling = null; 21888 } 21889 21890 break; 21891 } 21892 21893 case 'collapsed': 21894 { 21895 // Any insertions at the end of the tail list after this point 21896 // should be invisible. If there are already mounted boundaries 21897 // anything before them are not considered for collapsing. 21898 // Therefore we need to go through the whole tail to find if 21899 // there are any. 21900 var _tailNode = renderState.tail; 21901 var _lastTailNode = null; 21902 21903 while (_tailNode !== null) { 21904 if (_tailNode.alternate !== null) { 21905 _lastTailNode = _tailNode; 21906 } 21907 21908 _tailNode = _tailNode.sibling; 21909 } // Next we're simply going to delete all insertions after the 21910 // last rendered item. 21911 21912 21913 if (_lastTailNode === null) { 21914 // All remaining items in the tail are insertions. 21915 if (!hasRenderedATailFallback && renderState.tail !== null) { 21916 // We suspended during the head. We want to show at least one 21917 // row at the tail. So we'll keep on and cut off the rest. 21918 renderState.tail.sibling = null; 21919 } else { 21920 renderState.tail = null; 21921 } 21922 } else { 21923 // Detach the insertion after the last node that was already 21924 // inserted. 21925 _lastTailNode.sibling = null; 21926 } 21927 21928 break; 21929 } 21930 } 21931 } 21932 21933 function bubbleProperties(completedWork) { 21934 var didBailout = completedWork.alternate !== null && completedWork.alternate.child === completedWork.child; 21935 var newChildLanes = NoLanes; 21936 var subtreeFlags = NoFlags; 21937 21938 if (!didBailout) { 21939 // Bubble up the earliest expiration time. 21940 if ( (completedWork.mode & ProfileMode) !== NoMode) { 21941 // In profiling mode, resetChildExpirationTime is also used to reset 21942 // profiler durations. 21943 var actualDuration = completedWork.actualDuration; 21944 var treeBaseDuration = completedWork.selfBaseDuration; 21945 var child = completedWork.child; 21946 21947 while (child !== null) { 21948 newChildLanes = mergeLanes(newChildLanes, mergeLanes(child.lanes, child.childLanes)); 21949 subtreeFlags |= child.subtreeFlags; 21950 subtreeFlags |= child.flags; // When a fiber is cloned, its actualDuration is reset to 0. This value will 21951 // only be updated if work is done on the fiber (i.e. it doesn't bailout). 21952 // When work is done, it should bubble to the parent's actualDuration. If 21953 // the fiber has not been cloned though, (meaning no work was done), then 21954 // this value will reflect the amount of time spent working on a previous 21955 // render. In that case it should not bubble. We determine whether it was 21956 // cloned by comparing the child pointer. 21957 21958 actualDuration += child.actualDuration; 21959 treeBaseDuration += child.treeBaseDuration; 21960 child = child.sibling; 21961 } 21962 21963 completedWork.actualDuration = actualDuration; 21964 completedWork.treeBaseDuration = treeBaseDuration; 21965 } else { 21966 var _child = completedWork.child; 21967 21968 while (_child !== null) { 21969 newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child.lanes, _child.childLanes)); 21970 subtreeFlags |= _child.subtreeFlags; 21971 subtreeFlags |= _child.flags; // Update the return pointer so the tree is consistent. This is a code 21972 // smell because it assumes the commit phase is never concurrent with 21973 // the render phase. Will address during refactor to alternate model. 21974 21975 _child.return = completedWork; 21976 _child = _child.sibling; 21977 } 21978 } 21979 21980 completedWork.subtreeFlags |= subtreeFlags; 21981 } else { 21982 // Bubble up the earliest expiration time. 21983 if ( (completedWork.mode & ProfileMode) !== NoMode) { 21984 // In profiling mode, resetChildExpirationTime is also used to reset 21985 // profiler durations. 21986 var _treeBaseDuration = completedWork.selfBaseDuration; 21987 var _child2 = completedWork.child; 21988 21989 while (_child2 !== null) { 21990 newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child2.lanes, _child2.childLanes)); // "Static" flags share the lifetime of the fiber/hook they belong to, 21991 // so we should bubble those up even during a bailout. All the other 21992 // flags have a lifetime only of a single render + commit, so we should 21993 // ignore them. 21994 21995 subtreeFlags |= _child2.subtreeFlags & StaticMask; 21996 subtreeFlags |= _child2.flags & StaticMask; 21997 _treeBaseDuration += _child2.treeBaseDuration; 21998 _child2 = _child2.sibling; 21999 } 22000 22001 completedWork.treeBaseDuration = _treeBaseDuration; 22002 } else { 22003 var _child3 = completedWork.child; 22004 22005 while (_child3 !== null) { 22006 newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child3.lanes, _child3.childLanes)); // "Static" flags share the lifetime of the fiber/hook they belong to, 22007 // so we should bubble those up even during a bailout. All the other 22008 // flags have a lifetime only of a single render + commit, so we should 22009 // ignore them. 22010 22011 subtreeFlags |= _child3.subtreeFlags & StaticMask; 22012 subtreeFlags |= _child3.flags & StaticMask; // Update the return pointer so the tree is consistent. This is a code 22013 // smell because it assumes the commit phase is never concurrent with 22014 // the render phase. Will address during refactor to alternate model. 22015 22016 _child3.return = completedWork; 22017 _child3 = _child3.sibling; 22018 } 22019 } 22020 22021 completedWork.subtreeFlags |= subtreeFlags; 22022 } 22023 22024 completedWork.childLanes = newChildLanes; 22025 return didBailout; 22026 } 22027 22028 function completeDehydratedSuspenseBoundary(current, workInProgress, nextState) { 22029 if (hasUnhydratedTailNodes() && (workInProgress.mode & ConcurrentMode) !== NoMode && (workInProgress.flags & DidCapture) === NoFlags) { 22030 warnIfUnhydratedTailNodes(workInProgress); 22031 resetHydrationState(); 22032 workInProgress.flags |= ForceClientRender | Incomplete | ShouldCapture; 22033 return false; 22034 } 22035 22036 var wasHydrated = popHydrationState(workInProgress); 22037 22038 if (nextState !== null && nextState.dehydrated !== null) { 22039 // We might be inside a hydration state the first time we're picking up this 22040 // Suspense boundary, and also after we've reentered it for further hydration. 22041 if (current === null) { 22042 if (!wasHydrated) { 22043 throw new Error('A dehydrated suspense component was completed without a hydrated node. ' + 'This is probably a bug in React.'); 22044 } 22045 22046 prepareToHydrateHostSuspenseInstance(workInProgress); 22047 bubbleProperties(workInProgress); 22048 22049 { 22050 if ((workInProgress.mode & ProfileMode) !== NoMode) { 22051 var isTimedOutSuspense = nextState !== null; 22052 22053 if (isTimedOutSuspense) { 22054 // Don't count time spent in a timed out Suspense subtree as part of the base duration. 22055 var primaryChildFragment = workInProgress.child; 22056 22057 if (primaryChildFragment !== null) { 22058 // $FlowFixMe Flow doesn't support type casting in combination with the -= operator 22059 workInProgress.treeBaseDuration -= primaryChildFragment.treeBaseDuration; 22060 } 22061 } 22062 } 22063 } 22064 22065 return false; 22066 } else { 22067 // We might have reentered this boundary to hydrate it. If so, we need to reset the hydration 22068 // state since we're now exiting out of it. popHydrationState doesn't do that for us. 22069 resetHydrationState(); 22070 22071 if ((workInProgress.flags & DidCapture) === NoFlags) { 22072 // This boundary did not suspend so it's now hydrated and unsuspended. 22073 workInProgress.memoizedState = null; 22074 } // If nothing suspended, we need to schedule an effect to mark this boundary 22075 // as having hydrated so events know that they're free to be invoked. 22076 // It's also a signal to replay events and the suspense callback. 22077 // If something suspended, schedule an effect to attach retry listeners. 22078 // So we might as well always mark this. 22079 22080 22081 workInProgress.flags |= Update; 22082 bubbleProperties(workInProgress); 22083 22084 { 22085 if ((workInProgress.mode & ProfileMode) !== NoMode) { 22086 var _isTimedOutSuspense = nextState !== null; 22087 22088 if (_isTimedOutSuspense) { 22089 // Don't count time spent in a timed out Suspense subtree as part of the base duration. 22090 var _primaryChildFragment = workInProgress.child; 22091 22092 if (_primaryChildFragment !== null) { 22093 // $FlowFixMe Flow doesn't support type casting in combination with the -= operator 22094 workInProgress.treeBaseDuration -= _primaryChildFragment.treeBaseDuration; 22095 } 22096 } 22097 } 22098 } 22099 22100 return false; 22101 } 22102 } else { 22103 // Successfully completed this tree. If this was a forced client render, 22104 // there may have been recoverable errors during first hydration 22105 // attempt. If so, add them to a queue so we can log them in the 22106 // commit phase. 22107 upgradeHydrationErrorsToRecoverable(); // Fall through to normal Suspense path 22108 22109 return true; 22110 } 22111 } 22112 22113 function completeWork(current, workInProgress, renderLanes) { 22114 var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing 22115 // to the current tree provider fiber is just as fast and less error-prone. 22116 // Ideally we would have a special version of the work loop only 22117 // for hydration. 22118 22119 popTreeContext(workInProgress); 22120 22121 switch (workInProgress.tag) { 22122 case IndeterminateComponent: 22123 case LazyComponent: 22124 case SimpleMemoComponent: 22125 case FunctionComponent: 22126 case ForwardRef: 22127 case Fragment: 22128 case Mode: 22129 case Profiler: 22130 case ContextConsumer: 22131 case MemoComponent: 22132 bubbleProperties(workInProgress); 22133 return null; 22134 22135 case ClassComponent: 22136 { 22137 var Component = workInProgress.type; 22138 22139 if (isContextProvider(Component)) { 22140 popContext(workInProgress); 22141 } 22142 22143 bubbleProperties(workInProgress); 22144 return null; 22145 } 22146 22147 case HostRoot: 22148 { 22149 var fiberRoot = workInProgress.stateNode; 22150 popHostContainer(workInProgress); 22151 popTopLevelContextObject(workInProgress); 22152 resetWorkInProgressVersions(); 22153 22154 if (fiberRoot.pendingContext) { 22155 fiberRoot.context = fiberRoot.pendingContext; 22156 fiberRoot.pendingContext = null; 22157 } 22158 22159 if (current === null || current.child === null) { 22160 // If we hydrated, pop so that we can delete any remaining children 22161 // that weren't hydrated. 22162 var wasHydrated = popHydrationState(workInProgress); 22163 22164 if (wasHydrated) { 22165 // If we hydrated, then we'll need to schedule an update for 22166 // the commit side-effects on the root. 22167 markUpdate(workInProgress); 22168 } else { 22169 if (current !== null) { 22170 var prevState = current.memoizedState; 22171 22172 if ( // Check if this is a client root 22173 !prevState.isDehydrated || // Check if we reverted to client rendering (e.g. due to an error) 22174 (workInProgress.flags & ForceClientRender) !== NoFlags) { 22175 // Schedule an effect to clear this container at the start of the 22176 // next commit. This handles the case of React rendering into a 22177 // container with previous children. It's also safe to do for 22178 // updates too, because current.child would only be null if the 22179 // previous render was null (so the container would already 22180 // be empty). 22181 workInProgress.flags |= Snapshot; // If this was a forced client render, there may have been 22182 // recoverable errors during first hydration attempt. If so, add 22183 // them to a queue so we can log them in the commit phase. 22184 22185 upgradeHydrationErrorsToRecoverable(); 22186 } 22187 } 22188 } 22189 } 22190 22191 updateHostContainer(current, workInProgress); 22192 bubbleProperties(workInProgress); 22193 22194 return null; 22195 } 22196 22197 case HostComponent: 22198 { 22199 popHostContext(workInProgress); 22200 var rootContainerInstance = getRootHostContainer(); 22201 var type = workInProgress.type; 22202 22203 if (current !== null && workInProgress.stateNode != null) { 22204 updateHostComponent$1(current, workInProgress, type, newProps, rootContainerInstance); 22205 22206 if (current.ref !== workInProgress.ref) { 22207 markRef$1(workInProgress); 22208 } 22209 } else { 22210 if (!newProps) { 22211 if (workInProgress.stateNode === null) { 22212 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.'); 22213 } // This can happen when we abort work. 22214 22215 22216 bubbleProperties(workInProgress); 22217 return null; 22218 } 22219 22220 var currentHostContext = getHostContext(); // TODO: Move createInstance to beginWork and keep it on a context 22221 // "stack" as the parent. Then append children as we go in beginWork 22222 // or completeWork depending on whether we want to add them top->down or 22223 // bottom->up. Top->down is faster in IE11. 22224 22225 var _wasHydrated = popHydrationState(workInProgress); 22226 22227 if (_wasHydrated) { 22228 // TODO: Move this and createInstance step into the beginPhase 22229 // to consolidate. 22230 if (prepareToHydrateHostInstance(workInProgress, rootContainerInstance, currentHostContext)) { 22231 // If changes to the hydrated node need to be applied at the 22232 // commit-phase we mark this as such. 22233 markUpdate(workInProgress); 22234 } 22235 } else { 22236 var instance = createInstance(type, newProps, rootContainerInstance, currentHostContext, workInProgress); 22237 appendAllChildren(instance, workInProgress, false, false); 22238 workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount. 22239 // (eg DOM renderer supports auto-focus for certain elements). 22240 // Make sure such renderers get scheduled for later work. 22241 22242 if (finalizeInitialChildren(instance, type, newProps, rootContainerInstance)) { 22243 markUpdate(workInProgress); 22244 } 22245 } 22246 22247 if (workInProgress.ref !== null) { 22248 // If there is a ref on a host node we need to schedule a callback 22249 markRef$1(workInProgress); 22250 } 22251 } 22252 22253 bubbleProperties(workInProgress); 22254 return null; 22255 } 22256 22257 case HostText: 22258 { 22259 var newText = newProps; 22260 22261 if (current && workInProgress.stateNode != null) { 22262 var oldText = current.memoizedProps; // If we have an alternate, that means this is an update and we need 22263 // to schedule a side-effect to do the updates. 22264 22265 updateHostText$1(current, workInProgress, oldText, newText); 22266 } else { 22267 if (typeof newText !== 'string') { 22268 if (workInProgress.stateNode === null) { 22269 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.'); 22270 } // This can happen when we abort work. 22271 22272 } 22273 22274 var _rootContainerInstance = getRootHostContainer(); 22275 22276 var _currentHostContext = getHostContext(); 22277 22278 var _wasHydrated2 = popHydrationState(workInProgress); 22279 22280 if (_wasHydrated2) { 22281 if (prepareToHydrateHostTextInstance(workInProgress)) { 22282 markUpdate(workInProgress); 22283 } 22284 } else { 22285 workInProgress.stateNode = createTextInstance(newText, _rootContainerInstance, _currentHostContext, workInProgress); 22286 } 22287 } 22288 22289 bubbleProperties(workInProgress); 22290 return null; 22291 } 22292 22293 case SuspenseComponent: 22294 { 22295 popSuspenseContext(workInProgress); 22296 var nextState = workInProgress.memoizedState; // Special path for dehydrated boundaries. We may eventually move this 22297 // to its own fiber type so that we can add other kinds of hydration 22298 // boundaries that aren't associated with a Suspense tree. In anticipation 22299 // of such a refactor, all the hydration logic is contained in 22300 // this branch. 22301 22302 if (current === null || current.memoizedState !== null && current.memoizedState.dehydrated !== null) { 22303 var fallthroughToNormalSuspensePath = completeDehydratedSuspenseBoundary(current, workInProgress, nextState); 22304 22305 if (!fallthroughToNormalSuspensePath) { 22306 if (workInProgress.flags & ShouldCapture) { 22307 // Special case. There were remaining unhydrated nodes. We treat 22308 // this as a mismatch. Revert to client rendering. 22309 return workInProgress; 22310 } else { 22311 // Did not finish hydrating, either because this is the initial 22312 // render or because something suspended. 22313 return null; 22314 } 22315 } // Continue with the normal Suspense path. 22316 22317 } 22318 22319 if ((workInProgress.flags & DidCapture) !== NoFlags) { 22320 // Something suspended. Re-render with the fallback children. 22321 workInProgress.lanes = renderLanes; // Do not reset the effect list. 22322 22323 if ( (workInProgress.mode & ProfileMode) !== NoMode) { 22324 transferActualDuration(workInProgress); 22325 } // Don't bubble properties in this case. 22326 22327 22328 return workInProgress; 22329 } 22330 22331 var nextDidTimeout = nextState !== null; 22332 var prevDidTimeout = current !== null && current.memoizedState !== null; 22333 // a passive effect, which is when we process the transitions 22334 22335 22336 if (nextDidTimeout !== prevDidTimeout) { 22337 // an effect to toggle the subtree's visibility. When we switch from 22338 // fallback -> primary, the inner Offscreen fiber schedules this effect 22339 // as part of its normal complete phase. But when we switch from 22340 // primary -> fallback, the inner Offscreen fiber does not have a complete 22341 // phase. So we need to schedule its effect here. 22342 // 22343 // We also use this flag to connect/disconnect the effects, but the same 22344 // logic applies: when re-connecting, the Offscreen fiber's complete 22345 // phase will handle scheduling the effect. It's only when the fallback 22346 // is active that we have to do anything special. 22347 22348 22349 if (nextDidTimeout) { 22350 var _offscreenFiber2 = workInProgress.child; 22351 _offscreenFiber2.flags |= Visibility; // TODO: This will still suspend a synchronous tree if anything 22352 // in the concurrent tree already suspended during this render. 22353 // This is a known bug. 22354 22355 if ((workInProgress.mode & ConcurrentMode) !== NoMode) { 22356 // TODO: Move this back to throwException because this is too late 22357 // if this is a large tree which is common for initial loads. We 22358 // don't know if we should restart a render or not until we get 22359 // this marker, and this is too late. 22360 // If this render already had a ping or lower pri updates, 22361 // and this is the first time we know we're going to suspend we 22362 // should be able to immediately restart from within throwException. 22363 var hasInvisibleChildContext = current === null && (workInProgress.memoizedProps.unstable_avoidThisFallback !== true || !enableSuspenseAvoidThisFallback); 22364 22365 if (hasInvisibleChildContext || hasSuspenseContext(suspenseStackCursor.current, InvisibleParentSuspenseContext)) { 22366 // If this was in an invisible tree or a new render, then showing 22367 // this boundary is ok. 22368 renderDidSuspend(); 22369 } else { 22370 // Otherwise, we're going to have to hide content so we should 22371 // suspend for longer if possible. 22372 renderDidSuspendDelayIfPossible(); 22373 } 22374 } 22375 } 22376 } 22377 22378 var wakeables = workInProgress.updateQueue; 22379 22380 if (wakeables !== null) { 22381 // Schedule an effect to attach a retry listener to the promise. 22382 // TODO: Move to passive phase 22383 workInProgress.flags |= Update; 22384 } 22385 22386 bubbleProperties(workInProgress); 22387 22388 { 22389 if ((workInProgress.mode & ProfileMode) !== NoMode) { 22390 if (nextDidTimeout) { 22391 // Don't count time spent in a timed out Suspense subtree as part of the base duration. 22392 var primaryChildFragment = workInProgress.child; 22393 22394 if (primaryChildFragment !== null) { 22395 // $FlowFixMe Flow doesn't support type casting in combination with the -= operator 22396 workInProgress.treeBaseDuration -= primaryChildFragment.treeBaseDuration; 22397 } 22398 } 22399 } 22400 } 22401 22402 return null; 22403 } 22404 22405 case HostPortal: 22406 popHostContainer(workInProgress); 22407 updateHostContainer(current, workInProgress); 22408 22409 if (current === null) { 22410 preparePortalMount(workInProgress.stateNode.containerInfo); 22411 } 22412 22413 bubbleProperties(workInProgress); 22414 return null; 22415 22416 case ContextProvider: 22417 // Pop provider fiber 22418 var context = workInProgress.type._context; 22419 popProvider(context, workInProgress); 22420 bubbleProperties(workInProgress); 22421 return null; 22422 22423 case IncompleteClassComponent: 22424 { 22425 // Same as class component case. I put it down here so that the tags are 22426 // sequential to ensure this switch is compiled to a jump table. 22427 var _Component = workInProgress.type; 22428 22429 if (isContextProvider(_Component)) { 22430 popContext(workInProgress); 22431 } 22432 22433 bubbleProperties(workInProgress); 22434 return null; 22435 } 22436 22437 case SuspenseListComponent: 22438 { 22439 popSuspenseContext(workInProgress); 22440 var renderState = workInProgress.memoizedState; 22441 22442 if (renderState === null) { 22443 // We're running in the default, "independent" mode. 22444 // We don't do anything in this mode. 22445 bubbleProperties(workInProgress); 22446 return null; 22447 } 22448 22449 var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags; 22450 var renderedTail = renderState.rendering; 22451 22452 if (renderedTail === null) { 22453 // We just rendered the head. 22454 if (!didSuspendAlready) { 22455 // This is the first pass. We need to figure out if anything is still 22456 // suspended in the rendered set. 22457 // If new content unsuspended, but there's still some content that 22458 // didn't. Then we need to do a second pass that forces everything 22459 // to keep showing their fallbacks. 22460 // We might be suspended if something in this render pass suspended, or 22461 // something in the previous committed pass suspended. Otherwise, 22462 // there's no chance so we can skip the expensive call to 22463 // findFirstSuspended. 22464 var cannotBeSuspended = renderHasNotSuspendedYet() && (current === null || (current.flags & DidCapture) === NoFlags); 22465 22466 if (!cannotBeSuspended) { 22467 var row = workInProgress.child; 22468 22469 while (row !== null) { 22470 var suspended = findFirstSuspended(row); 22471 22472 if (suspended !== null) { 22473 didSuspendAlready = true; 22474 workInProgress.flags |= DidCapture; 22475 cutOffTailIfNeeded(renderState, false); // If this is a newly suspended tree, it might not get committed as 22476 // part of the second pass. In that case nothing will subscribe to 22477 // its thenables. Instead, we'll transfer its thenables to the 22478 // SuspenseList so that it can retry if they resolve. 22479 // There might be multiple of these in the list but since we're 22480 // going to wait for all of them anyway, it doesn't really matter 22481 // which ones gets to ping. In theory we could get clever and keep 22482 // track of how many dependencies remain but it gets tricky because 22483 // in the meantime, we can add/remove/change items and dependencies. 22484 // We might bail out of the loop before finding any but that 22485 // doesn't matter since that means that the other boundaries that 22486 // we did find already has their listeners attached. 22487 22488 var newThenables = suspended.updateQueue; 22489 22490 if (newThenables !== null) { 22491 workInProgress.updateQueue = newThenables; 22492 workInProgress.flags |= Update; 22493 } // Rerender the whole list, but this time, we'll force fallbacks 22494 // to stay in place. 22495 // Reset the effect flags before doing the second pass since that's now invalid. 22496 // Reset the child fibers to their original state. 22497 22498 22499 workInProgress.subtreeFlags = NoFlags; 22500 resetChildFibers(workInProgress, renderLanes); // Set up the Suspense Context to force suspense and immediately 22501 // rerender the children. 22502 22503 pushSuspenseContext(workInProgress, setShallowSuspenseContext(suspenseStackCursor.current, ForceSuspenseFallback)); // Don't bubble properties in this case. 22504 22505 return workInProgress.child; 22506 } 22507 22508 row = row.sibling; 22509 } 22510 } 22511 22512 if (renderState.tail !== null && now() > getRenderTargetTime()) { 22513 // We have already passed our CPU deadline but we still have rows 22514 // left in the tail. We'll just give up further attempts to render 22515 // the main content and only render fallbacks. 22516 workInProgress.flags |= DidCapture; 22517 didSuspendAlready = true; 22518 cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this 22519 // to get it started back up to attempt the next item. While in terms 22520 // of priority this work has the same priority as this current render, 22521 // it's not part of the same transition once the transition has 22522 // committed. If it's sync, we still want to yield so that it can be 22523 // painted. Conceptually, this is really the same as pinging. 22524 // We can use any RetryLane even if it's the one currently rendering 22525 // since we're leaving it behind on this node. 22526 22527 workInProgress.lanes = SomeRetryLane; 22528 } 22529 } else { 22530 cutOffTailIfNeeded(renderState, false); 22531 } // Next we're going to render the tail. 22532 22533 } else { 22534 // Append the rendered row to the child list. 22535 if (!didSuspendAlready) { 22536 var _suspended = findFirstSuspended(renderedTail); 22537 22538 if (_suspended !== null) { 22539 workInProgress.flags |= DidCapture; 22540 didSuspendAlready = true; // Ensure we transfer the update queue to the parent so that it doesn't 22541 // get lost if this row ends up dropped during a second pass. 22542 22543 var _newThenables = _suspended.updateQueue; 22544 22545 if (_newThenables !== null) { 22546 workInProgress.updateQueue = _newThenables; 22547 workInProgress.flags |= Update; 22548 } 22549 22550 cutOffTailIfNeeded(renderState, true); // This might have been modified. 22551 22552 if (renderState.tail === null && renderState.tailMode === 'hidden' && !renderedTail.alternate && !getIsHydrating() // We don't cut it if we're hydrating. 22553 ) { 22554 // We're done. 22555 bubbleProperties(workInProgress); 22556 return null; 22557 } 22558 } else if ( // The time it took to render last row is greater than the remaining 22559 // time we have to render. So rendering one more row would likely 22560 // exceed it. 22561 now() * 2 - renderState.renderingStartTime > getRenderTargetTime() && renderLanes !== OffscreenLane) { 22562 // We have now passed our CPU deadline and we'll just give up further 22563 // attempts to render the main content and only render fallbacks. 22564 // The assumption is that this is usually faster. 22565 workInProgress.flags |= DidCapture; 22566 didSuspendAlready = true; 22567 cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this 22568 // to get it started back up to attempt the next item. While in terms 22569 // of priority this work has the same priority as this current render, 22570 // it's not part of the same transition once the transition has 22571 // committed. If it's sync, we still want to yield so that it can be 22572 // painted. Conceptually, this is really the same as pinging. 22573 // We can use any RetryLane even if it's the one currently rendering 22574 // since we're leaving it behind on this node. 22575 22576 workInProgress.lanes = SomeRetryLane; 22577 } 22578 } 22579 22580 if (renderState.isBackwards) { 22581 // The effect list of the backwards tail will have been added 22582 // to the end. This breaks the guarantee that life-cycles fire in 22583 // sibling order but that isn't a strong guarantee promised by React. 22584 // Especially since these might also just pop in during future commits. 22585 // Append to the beginning of the list. 22586 renderedTail.sibling = workInProgress.child; 22587 workInProgress.child = renderedTail; 22588 } else { 22589 var previousSibling = renderState.last; 22590 22591 if (previousSibling !== null) { 22592 previousSibling.sibling = renderedTail; 22593 } else { 22594 workInProgress.child = renderedTail; 22595 } 22596 22597 renderState.last = renderedTail; 22598 } 22599 } 22600 22601 if (renderState.tail !== null) { 22602 // We still have tail rows to render. 22603 // Pop a row. 22604 var next = renderState.tail; 22605 renderState.rendering = next; 22606 renderState.tail = next.sibling; 22607 renderState.renderingStartTime = now(); 22608 next.sibling = null; // Restore the context. 22609 // TODO: We can probably just avoid popping it instead and only 22610 // setting it the first time we go from not suspended to suspended. 22611 22612 var suspenseContext = suspenseStackCursor.current; 22613 22614 if (didSuspendAlready) { 22615 suspenseContext = setShallowSuspenseContext(suspenseContext, ForceSuspenseFallback); 22616 } else { 22617 suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); 22618 } 22619 22620 pushSuspenseContext(workInProgress, suspenseContext); // Do a pass over the next row. 22621 // Don't bubble properties in this case. 22622 22623 return next; 22624 } 22625 22626 bubbleProperties(workInProgress); 22627 return null; 22628 } 22629 22630 case ScopeComponent: 22631 { 22632 22633 break; 22634 } 22635 22636 case OffscreenComponent: 22637 case LegacyHiddenComponent: 22638 { 22639 popRenderLanes(workInProgress); 22640 var _nextState = workInProgress.memoizedState; 22641 var nextIsHidden = _nextState !== null; 22642 22643 if (current !== null) { 22644 var _prevState = current.memoizedState; 22645 var prevIsHidden = _prevState !== null; 22646 22647 if (prevIsHidden !== nextIsHidden && ( // LegacyHidden doesn't do any hiding — it only pre-renders. 22648 !enableLegacyHidden )) { 22649 workInProgress.flags |= Visibility; 22650 } 22651 } 22652 22653 if (!nextIsHidden || (workInProgress.mode & ConcurrentMode) === NoMode) { 22654 bubbleProperties(workInProgress); 22655 } else { 22656 // Don't bubble properties for hidden children unless we're rendering 22657 // at offscreen priority. 22658 if (includesSomeLane(subtreeRenderLanes, OffscreenLane)) { 22659 bubbleProperties(workInProgress); 22660 22661 { 22662 // Check if there was an insertion or update in the hidden subtree. 22663 // If so, we need to hide those nodes in the commit phase, so 22664 // schedule a visibility effect. 22665 if ( workInProgress.subtreeFlags & (Placement | Update)) { 22666 workInProgress.flags |= Visibility; 22667 } 22668 } 22669 } 22670 } 22671 return null; 22672 } 22673 22674 case CacheComponent: 22675 { 22676 22677 return null; 22678 } 22679 22680 case TracingMarkerComponent: 22681 { 22682 22683 return null; 22684 } 22685 } 22686 22687 throw new Error("Unknown unit of work tag (" + workInProgress.tag + "). This error is likely caused by a bug in " + 'React. Please file an issue.'); 22688 } 22689 22690 function unwindWork(current, workInProgress, renderLanes) { 22691 // Note: This intentionally doesn't check if we're hydrating because comparing 22692 // to the current tree provider fiber is just as fast and less error-prone. 22693 // Ideally we would have a special version of the work loop only 22694 // for hydration. 22695 popTreeContext(workInProgress); 22696 22697 switch (workInProgress.tag) { 22698 case ClassComponent: 22699 { 22700 var Component = workInProgress.type; 22701 22702 if (isContextProvider(Component)) { 22703 popContext(workInProgress); 22704 } 22705 22706 var flags = workInProgress.flags; 22707 22708 if (flags & ShouldCapture) { 22709 workInProgress.flags = flags & ~ShouldCapture | DidCapture; 22710 22711 if ( (workInProgress.mode & ProfileMode) !== NoMode) { 22712 transferActualDuration(workInProgress); 22713 } 22714 22715 return workInProgress; 22716 } 22717 22718 return null; 22719 } 22720 22721 case HostRoot: 22722 { 22723 var root = workInProgress.stateNode; 22724 popHostContainer(workInProgress); 22725 popTopLevelContextObject(workInProgress); 22726 resetWorkInProgressVersions(); 22727 var _flags = workInProgress.flags; 22728 22729 if ((_flags & ShouldCapture) !== NoFlags && (_flags & DidCapture) === NoFlags) { 22730 // There was an error during render that wasn't captured by a suspense 22731 // boundary. Do a second pass on the root to unmount the children. 22732 workInProgress.flags = _flags & ~ShouldCapture | DidCapture; 22733 return workInProgress; 22734 } // We unwound to the root without completing it. Exit. 22735 22736 22737 return null; 22738 } 22739 22740 case HostComponent: 22741 { 22742 // TODO: popHydrationState 22743 popHostContext(workInProgress); 22744 return null; 22745 } 22746 22747 case SuspenseComponent: 22748 { 22749 popSuspenseContext(workInProgress); 22750 var suspenseState = workInProgress.memoizedState; 22751 22752 if (suspenseState !== null && suspenseState.dehydrated !== null) { 22753 if (workInProgress.alternate === null) { 22754 throw new Error('Threw in newly mounted dehydrated component. This is likely a bug in ' + 'React. Please file an issue.'); 22755 } 22756 22757 resetHydrationState(); 22758 } 22759 22760 var _flags2 = workInProgress.flags; 22761 22762 if (_flags2 & ShouldCapture) { 22763 workInProgress.flags = _flags2 & ~ShouldCapture | DidCapture; // Captured a suspense effect. Re-render the boundary. 22764 22765 if ( (workInProgress.mode & ProfileMode) !== NoMode) { 22766 transferActualDuration(workInProgress); 22767 } 22768 22769 return workInProgress; 22770 } 22771 22772 return null; 22773 } 22774 22775 case SuspenseListComponent: 22776 { 22777 popSuspenseContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been 22778 // caught by a nested boundary. If not, it should bubble through. 22779 22780 return null; 22781 } 22782 22783 case HostPortal: 22784 popHostContainer(workInProgress); 22785 return null; 22786 22787 case ContextProvider: 22788 var context = workInProgress.type._context; 22789 popProvider(context, workInProgress); 22790 return null; 22791 22792 case OffscreenComponent: 22793 case LegacyHiddenComponent: 22794 popRenderLanes(workInProgress); 22795 return null; 22796 22797 case CacheComponent: 22798 22799 return null; 22800 22801 default: 22802 return null; 22803 } 22804 } 22805 22806 function unwindInterruptedWork(current, interruptedWork, renderLanes) { 22807 // Note: This intentionally doesn't check if we're hydrating because comparing 22808 // to the current tree provider fiber is just as fast and less error-prone. 22809 // Ideally we would have a special version of the work loop only 22810 // for hydration. 22811 popTreeContext(interruptedWork); 22812 22813 switch (interruptedWork.tag) { 22814 case ClassComponent: 22815 { 22816 var childContextTypes = interruptedWork.type.childContextTypes; 22817 22818 if (childContextTypes !== null && childContextTypes !== undefined) { 22819 popContext(interruptedWork); 22820 } 22821 22822 break; 22823 } 22824 22825 case HostRoot: 22826 { 22827 var root = interruptedWork.stateNode; 22828 popHostContainer(interruptedWork); 22829 popTopLevelContextObject(interruptedWork); 22830 resetWorkInProgressVersions(); 22831 break; 22832 } 22833 22834 case HostComponent: 22835 { 22836 popHostContext(interruptedWork); 22837 break; 22838 } 22839 22840 case HostPortal: 22841 popHostContainer(interruptedWork); 22842 break; 22843 22844 case SuspenseComponent: 22845 popSuspenseContext(interruptedWork); 22846 break; 22847 22848 case SuspenseListComponent: 22849 popSuspenseContext(interruptedWork); 22850 break; 22851 22852 case ContextProvider: 22853 var context = interruptedWork.type._context; 22854 popProvider(context, interruptedWork); 22855 break; 22856 22857 case OffscreenComponent: 22858 case LegacyHiddenComponent: 22859 popRenderLanes(interruptedWork); 22860 break; 22861 } 22862 } 22863 22864 var didWarnAboutUndefinedSnapshotBeforeUpdate = null; 22865 22866 { 22867 didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); 22868 } // Used during the commit phase to track the state of the Offscreen component stack. 22869 // Allows us to avoid traversing the return path to find the nearest Offscreen ancestor. 22870 // Only used when enableSuspenseLayoutEffectSemantics is enabled. 22871 22872 22873 var offscreenSubtreeIsHidden = false; 22874 var offscreenSubtreeWasHidden = false; 22875 var PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set; 22876 var nextEffect = null; // Used for Profiling builds to track updaters. 22877 22878 var inProgressLanes = null; 22879 var inProgressRoot = null; 22880 function reportUncaughtErrorInDEV(error) { 22881 // Wrapping each small part of the commit phase into a guarded 22882 // callback is a bit too slow (https://github.com/facebook/react/pull/21666). 22883 // But we rely on it to surface errors to DEV tools like overlays 22884 // (https://github.com/facebook/react/issues/21712). 22885 // As a compromise, rethrow only caught errors in a guard. 22886 { 22887 invokeGuardedCallback(null, function () { 22888 throw error; 22889 }); 22890 clearCaughtError(); 22891 } 22892 } 22893 22894 var callComponentWillUnmountWithTimer = function (current, instance) { 22895 instance.props = current.memoizedProps; 22896 instance.state = current.memoizedState; 22897 22898 if ( current.mode & ProfileMode) { 22899 try { 22900 startLayoutEffectTimer(); 22901 instance.componentWillUnmount(); 22902 } finally { 22903 recordLayoutEffectDuration(current); 22904 } 22905 } else { 22906 instance.componentWillUnmount(); 22907 } 22908 }; // Capture errors so they don't interrupt mounting. 22909 22910 22911 function safelyCallCommitHookLayoutEffectListMount(current, nearestMountedAncestor) { 22912 try { 22913 commitHookEffectListMount(Layout, current); 22914 } catch (error) { 22915 captureCommitPhaseError(current, nearestMountedAncestor, error); 22916 } 22917 } // Capture errors so they don't interrupt unmounting. 22918 22919 22920 function safelyCallComponentWillUnmount(current, nearestMountedAncestor, instance) { 22921 try { 22922 callComponentWillUnmountWithTimer(current, instance); 22923 } catch (error) { 22924 captureCommitPhaseError(current, nearestMountedAncestor, error); 22925 } 22926 } // Capture errors so they don't interrupt mounting. 22927 22928 22929 function safelyCallComponentDidMount(current, nearestMountedAncestor, instance) { 22930 try { 22931 instance.componentDidMount(); 22932 } catch (error) { 22933 captureCommitPhaseError(current, nearestMountedAncestor, error); 22934 } 22935 } // Capture errors so they don't interrupt mounting. 22936 22937 22938 function safelyAttachRef(current, nearestMountedAncestor) { 22939 try { 22940 commitAttachRef(current); 22941 } catch (error) { 22942 captureCommitPhaseError(current, nearestMountedAncestor, error); 22943 } 22944 } 22945 22946 function safelyDetachRef(current, nearestMountedAncestor) { 22947 var ref = current.ref; 22948 22949 if (ref !== null) { 22950 if (typeof ref === 'function') { 22951 var retVal; 22952 22953 try { 22954 if (enableProfilerTimer && enableProfilerCommitHooks && current.mode & ProfileMode) { 22955 try { 22956 startLayoutEffectTimer(); 22957 retVal = ref(null); 22958 } finally { 22959 recordLayoutEffectDuration(current); 22960 } 22961 } else { 22962 retVal = ref(null); 22963 } 22964 } catch (error) { 22965 captureCommitPhaseError(current, nearestMountedAncestor, error); 22966 } 22967 22968 { 22969 if (typeof retVal === 'function') { 22970 error('Unexpected return value from a callback ref in %s. ' + 'A callback ref should not return a function.', getComponentNameFromFiber(current)); 22971 } 22972 } 22973 } else { 22974 ref.current = null; 22975 } 22976 } 22977 } 22978 22979 function safelyCallDestroy(current, nearestMountedAncestor, destroy) { 22980 try { 22981 destroy(); 22982 } catch (error) { 22983 captureCommitPhaseError(current, nearestMountedAncestor, error); 22984 } 22985 } 22986 22987 var focusedInstanceHandle = null; 22988 var shouldFireAfterActiveInstanceBlur = false; 22989 function commitBeforeMutationEffects(root, firstChild) { 22990 focusedInstanceHandle = prepareForCommit(root.containerInfo); 22991 nextEffect = firstChild; 22992 commitBeforeMutationEffects_begin(); // We no longer need to track the active instance fiber 22993 22994 var shouldFire = shouldFireAfterActiveInstanceBlur; 22995 shouldFireAfterActiveInstanceBlur = false; 22996 focusedInstanceHandle = null; 22997 return shouldFire; 22998 } 22999 23000 function commitBeforeMutationEffects_begin() { 23001 while (nextEffect !== null) { 23002 var fiber = nextEffect; // This phase is only used for beforeActiveInstanceBlur. 23003 23004 var child = fiber.child; 23005 23006 if ((fiber.subtreeFlags & BeforeMutationMask) !== NoFlags && child !== null) { 23007 child.return = fiber; 23008 nextEffect = child; 23009 } else { 23010 commitBeforeMutationEffects_complete(); 23011 } 23012 } 23013 } 23014 23015 function commitBeforeMutationEffects_complete() { 23016 while (nextEffect !== null) { 23017 var fiber = nextEffect; 23018 setCurrentFiber(fiber); 23019 23020 try { 23021 commitBeforeMutationEffectsOnFiber(fiber); 23022 } catch (error) { 23023 captureCommitPhaseError(fiber, fiber.return, error); 23024 } 23025 23026 resetCurrentFiber(); 23027 var sibling = fiber.sibling; 23028 23029 if (sibling !== null) { 23030 sibling.return = fiber.return; 23031 nextEffect = sibling; 23032 return; 23033 } 23034 23035 nextEffect = fiber.return; 23036 } 23037 } 23038 23039 function commitBeforeMutationEffectsOnFiber(finishedWork) { 23040 var current = finishedWork.alternate; 23041 var flags = finishedWork.flags; 23042 23043 if ((flags & Snapshot) !== NoFlags) { 23044 setCurrentFiber(finishedWork); 23045 23046 switch (finishedWork.tag) { 23047 case FunctionComponent: 23048 case ForwardRef: 23049 case SimpleMemoComponent: 23050 { 23051 break; 23052 } 23053 23054 case ClassComponent: 23055 { 23056 if (current !== null) { 23057 var prevProps = current.memoizedProps; 23058 var prevState = current.memoizedState; 23059 var instance = finishedWork.stateNode; // We could update instance props and state here, 23060 // but instead we rely on them being set during last render. 23061 // TODO: revisit this when we implement resuming. 23062 23063 { 23064 if (finishedWork.type === finishedWork.elementType && !didWarnAboutReassigningProps) { 23065 if (instance.props !== finishedWork.memoizedProps) { 23066 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'); 23067 } 23068 23069 if (instance.state !== finishedWork.memoizedState) { 23070 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'); 23071 } 23072 } 23073 } 23074 23075 var snapshot = instance.getSnapshotBeforeUpdate(finishedWork.elementType === finishedWork.type ? prevProps : resolveDefaultProps(finishedWork.type, prevProps), prevState); 23076 23077 { 23078 var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate; 23079 23080 if (snapshot === undefined && !didWarnSet.has(finishedWork.type)) { 23081 didWarnSet.add(finishedWork.type); 23082 23083 error('%s.getSnapshotBeforeUpdate(): A snapshot value (or null) ' + 'must be returned. You have returned undefined.', getComponentNameFromFiber(finishedWork)); 23084 } 23085 } 23086 23087 instance.__reactInternalSnapshotBeforeUpdate = snapshot; 23088 } 23089 23090 break; 23091 } 23092 23093 case HostRoot: 23094 { 23095 { 23096 var root = finishedWork.stateNode; 23097 clearContainer(root.containerInfo); 23098 } 23099 23100 break; 23101 } 23102 23103 case HostComponent: 23104 case HostText: 23105 case HostPortal: 23106 case IncompleteClassComponent: 23107 // Nothing to do for these component types 23108 break; 23109 23110 default: 23111 { 23112 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.'); 23113 } 23114 } 23115 23116 resetCurrentFiber(); 23117 } 23118 } 23119 23120 function commitHookEffectListUnmount(flags, finishedWork, nearestMountedAncestor) { 23121 var updateQueue = finishedWork.updateQueue; 23122 var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; 23123 23124 if (lastEffect !== null) { 23125 var firstEffect = lastEffect.next; 23126 var effect = firstEffect; 23127 23128 do { 23129 if ((effect.tag & flags) === flags) { 23130 // Unmount 23131 var destroy = effect.destroy; 23132 effect.destroy = undefined; 23133 23134 if (destroy !== undefined) { 23135 { 23136 if ((flags & Passive$1) !== NoFlags$1) { 23137 markComponentPassiveEffectUnmountStarted(finishedWork); 23138 } else if ((flags & Layout) !== NoFlags$1) { 23139 markComponentLayoutEffectUnmountStarted(finishedWork); 23140 } 23141 } 23142 23143 { 23144 if ((flags & Insertion) !== NoFlags$1) { 23145 setIsRunningInsertionEffect(true); 23146 } 23147 } 23148 23149 safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy); 23150 23151 { 23152 if ((flags & Insertion) !== NoFlags$1) { 23153 setIsRunningInsertionEffect(false); 23154 } 23155 } 23156 23157 { 23158 if ((flags & Passive$1) !== NoFlags$1) { 23159 markComponentPassiveEffectUnmountStopped(); 23160 } else if ((flags & Layout) !== NoFlags$1) { 23161 markComponentLayoutEffectUnmountStopped(); 23162 } 23163 } 23164 } 23165 } 23166 23167 effect = effect.next; 23168 } while (effect !== firstEffect); 23169 } 23170 } 23171 23172 function commitHookEffectListMount(flags, finishedWork) { 23173 var updateQueue = finishedWork.updateQueue; 23174 var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; 23175 23176 if (lastEffect !== null) { 23177 var firstEffect = lastEffect.next; 23178 var effect = firstEffect; 23179 23180 do { 23181 if ((effect.tag & flags) === flags) { 23182 { 23183 if ((flags & Passive$1) !== NoFlags$1) { 23184 markComponentPassiveEffectMountStarted(finishedWork); 23185 } else if ((flags & Layout) !== NoFlags$1) { 23186 markComponentLayoutEffectMountStarted(finishedWork); 23187 } 23188 } // Mount 23189 23190 23191 var create = effect.create; 23192 23193 { 23194 if ((flags & Insertion) !== NoFlags$1) { 23195 setIsRunningInsertionEffect(true); 23196 } 23197 } 23198 23199 effect.destroy = create(); 23200 23201 { 23202 if ((flags & Insertion) !== NoFlags$1) { 23203 setIsRunningInsertionEffect(false); 23204 } 23205 } 23206 23207 { 23208 if ((flags & Passive$1) !== NoFlags$1) { 23209 markComponentPassiveEffectMountStopped(); 23210 } else if ((flags & Layout) !== NoFlags$1) { 23211 markComponentLayoutEffectMountStopped(); 23212 } 23213 } 23214 23215 { 23216 var destroy = effect.destroy; 23217 23218 if (destroy !== undefined && typeof destroy !== 'function') { 23219 var hookName = void 0; 23220 23221 if ((effect.tag & Layout) !== NoFlags) { 23222 hookName = 'useLayoutEffect'; 23223 } else if ((effect.tag & Insertion) !== NoFlags) { 23224 hookName = 'useInsertionEffect'; 23225 } else { 23226 hookName = 'useEffect'; 23227 } 23228 23229 var addendum = void 0; 23230 23231 if (destroy === null) { 23232 addendum = ' You returned null. If your effect does not require clean ' + 'up, return undefined (or nothing).'; 23233 } else if (typeof destroy.then === 'function') { 23234 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'; 23235 } else { 23236 addendum = ' You returned: ' + destroy; 23237 } 23238 23239 error('%s must not return anything besides a function, ' + 'which is used for clean-up.%s', hookName, addendum); 23240 } 23241 } 23242 } 23243 23244 effect = effect.next; 23245 } while (effect !== firstEffect); 23246 } 23247 } 23248 23249 function commitPassiveEffectDurations(finishedRoot, finishedWork) { 23250 { 23251 // Only Profilers with work in their subtree will have an Update effect scheduled. 23252 if ((finishedWork.flags & Update) !== NoFlags) { 23253 switch (finishedWork.tag) { 23254 case Profiler: 23255 { 23256 var passiveEffectDuration = finishedWork.stateNode.passiveEffectDuration; 23257 var _finishedWork$memoize = finishedWork.memoizedProps, 23258 id = _finishedWork$memoize.id, 23259 onPostCommit = _finishedWork$memoize.onPostCommit; // This value will still reflect the previous commit phase. 23260 // It does not get reset until the start of the next commit phase. 23261 23262 var commitTime = getCommitTime(); 23263 var phase = finishedWork.alternate === null ? 'mount' : 'update'; 23264 23265 { 23266 if (isCurrentUpdateNested()) { 23267 phase = 'nested-update'; 23268 } 23269 } 23270 23271 if (typeof onPostCommit === 'function') { 23272 onPostCommit(id, phase, passiveEffectDuration, commitTime); 23273 } // Bubble times to the next nearest ancestor Profiler. 23274 // After we process that Profiler, we'll bubble further up. 23275 23276 23277 var parentFiber = finishedWork.return; 23278 23279 outer: while (parentFiber !== null) { 23280 switch (parentFiber.tag) { 23281 case HostRoot: 23282 var root = parentFiber.stateNode; 23283 root.passiveEffectDuration += passiveEffectDuration; 23284 break outer; 23285 23286 case Profiler: 23287 var parentStateNode = parentFiber.stateNode; 23288 parentStateNode.passiveEffectDuration += passiveEffectDuration; 23289 break outer; 23290 } 23291 23292 parentFiber = parentFiber.return; 23293 } 23294 23295 break; 23296 } 23297 } 23298 } 23299 } 23300 } 23301 23302 function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork, committedLanes) { 23303 if ((finishedWork.flags & LayoutMask) !== NoFlags) { 23304 switch (finishedWork.tag) { 23305 case FunctionComponent: 23306 case ForwardRef: 23307 case SimpleMemoComponent: 23308 { 23309 if ( !offscreenSubtreeWasHidden) { 23310 // At this point layout effects have already been destroyed (during mutation phase). 23311 // This is done to prevent sibling component effects from interfering with each other, 23312 // e.g. a destroy function in one component should never override a ref set 23313 // by a create function in another component during the same commit. 23314 if ( finishedWork.mode & ProfileMode) { 23315 try { 23316 startLayoutEffectTimer(); 23317 commitHookEffectListMount(Layout | HasEffect, finishedWork); 23318 } finally { 23319 recordLayoutEffectDuration(finishedWork); 23320 } 23321 } else { 23322 commitHookEffectListMount(Layout | HasEffect, finishedWork); 23323 } 23324 } 23325 23326 break; 23327 } 23328 23329 case ClassComponent: 23330 { 23331 var instance = finishedWork.stateNode; 23332 23333 if (finishedWork.flags & Update) { 23334 if (!offscreenSubtreeWasHidden) { 23335 if (current === null) { 23336 // We could update instance props and state here, 23337 // but instead we rely on them being set during last render. 23338 // TODO: revisit this when we implement resuming. 23339 { 23340 if (finishedWork.type === finishedWork.elementType && !didWarnAboutReassigningProps) { 23341 if (instance.props !== finishedWork.memoizedProps) { 23342 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'); 23343 } 23344 23345 if (instance.state !== finishedWork.memoizedState) { 23346 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'); 23347 } 23348 } 23349 } 23350 23351 if ( finishedWork.mode & ProfileMode) { 23352 try { 23353 startLayoutEffectTimer(); 23354 instance.componentDidMount(); 23355 } finally { 23356 recordLayoutEffectDuration(finishedWork); 23357 } 23358 } else { 23359 instance.componentDidMount(); 23360 } 23361 } else { 23362 var prevProps = finishedWork.elementType === finishedWork.type ? current.memoizedProps : resolveDefaultProps(finishedWork.type, current.memoizedProps); 23363 var prevState = current.memoizedState; // We could update instance props and state here, 23364 // but instead we rely on them being set during last render. 23365 // TODO: revisit this when we implement resuming. 23366 23367 { 23368 if (finishedWork.type === finishedWork.elementType && !didWarnAboutReassigningProps) { 23369 if (instance.props !== finishedWork.memoizedProps) { 23370 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'); 23371 } 23372 23373 if (instance.state !== finishedWork.memoizedState) { 23374 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'); 23375 } 23376 } 23377 } 23378 23379 if ( finishedWork.mode & ProfileMode) { 23380 try { 23381 startLayoutEffectTimer(); 23382 instance.componentDidUpdate(prevProps, prevState, instance.__reactInternalSnapshotBeforeUpdate); 23383 } finally { 23384 recordLayoutEffectDuration(finishedWork); 23385 } 23386 } else { 23387 instance.componentDidUpdate(prevProps, prevState, instance.__reactInternalSnapshotBeforeUpdate); 23388 } 23389 } 23390 } 23391 } // TODO: I think this is now always non-null by the time it reaches the 23392 // commit phase. Consider removing the type check. 23393 23394 23395 var updateQueue = finishedWork.updateQueue; 23396 23397 if (updateQueue !== null) { 23398 { 23399 if (finishedWork.type === finishedWork.elementType && !didWarnAboutReassigningProps) { 23400 if (instance.props !== finishedWork.memoizedProps) { 23401 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'); 23402 } 23403 23404 if (instance.state !== finishedWork.memoizedState) { 23405 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'); 23406 } 23407 } 23408 } // We could update instance props and state here, 23409 // but instead we rely on them being set during last render. 23410 // TODO: revisit this when we implement resuming. 23411 23412 23413 commitUpdateQueue(finishedWork, updateQueue, instance); 23414 } 23415 23416 break; 23417 } 23418 23419 case HostRoot: 23420 { 23421 // TODO: I think this is now always non-null by the time it reaches the 23422 // commit phase. Consider removing the type check. 23423 var _updateQueue = finishedWork.updateQueue; 23424 23425 if (_updateQueue !== null) { 23426 var _instance = null; 23427 23428 if (finishedWork.child !== null) { 23429 switch (finishedWork.child.tag) { 23430 case HostComponent: 23431 _instance = getPublicInstance(finishedWork.child.stateNode); 23432 break; 23433 23434 case ClassComponent: 23435 _instance = finishedWork.child.stateNode; 23436 break; 23437 } 23438 } 23439 23440 commitUpdateQueue(finishedWork, _updateQueue, _instance); 23441 } 23442 23443 break; 23444 } 23445 23446 case HostComponent: 23447 { 23448 var _instance2 = finishedWork.stateNode; // Renderers may schedule work to be done after host components are mounted 23449 // (eg DOM renderer may schedule auto-focus for inputs and form controls). 23450 // These effects should only be committed when components are first mounted, 23451 // aka when there is no current/alternate. 23452 23453 if (current === null && finishedWork.flags & Update) { 23454 var type = finishedWork.type; 23455 var props = finishedWork.memoizedProps; 23456 commitMount(_instance2, type, props); 23457 } 23458 23459 break; 23460 } 23461 23462 case HostText: 23463 { 23464 // We have no life-cycles associated with text. 23465 break; 23466 } 23467 23468 case HostPortal: 23469 { 23470 // We have no life-cycles associated with portals. 23471 break; 23472 } 23473 23474 case Profiler: 23475 { 23476 { 23477 var _finishedWork$memoize2 = finishedWork.memoizedProps, 23478 onCommit = _finishedWork$memoize2.onCommit, 23479 onRender = _finishedWork$memoize2.onRender; 23480 var effectDuration = finishedWork.stateNode.effectDuration; 23481 var commitTime = getCommitTime(); 23482 var phase = current === null ? 'mount' : 'update'; 23483 23484 { 23485 if (isCurrentUpdateNested()) { 23486 phase = 'nested-update'; 23487 } 23488 } 23489 23490 if (typeof onRender === 'function') { 23491 onRender(finishedWork.memoizedProps.id, phase, finishedWork.actualDuration, finishedWork.treeBaseDuration, finishedWork.actualStartTime, commitTime); 23492 } 23493 23494 { 23495 if (typeof onCommit === 'function') { 23496 onCommit(finishedWork.memoizedProps.id, phase, effectDuration, commitTime); 23497 } // Schedule a passive effect for this Profiler to call onPostCommit hooks. 23498 // This effect should be scheduled even if there is no onPostCommit callback for this Profiler, 23499 // because the effect is also where times bubble to parent Profilers. 23500 23501 23502 enqueuePendingPassiveProfilerEffect(finishedWork); // Propagate layout effect durations to the next nearest Profiler ancestor. 23503 // Do not reset these values until the next render so DevTools has a chance to read them first. 23504 23505 var parentFiber = finishedWork.return; 23506 23507 outer: while (parentFiber !== null) { 23508 switch (parentFiber.tag) { 23509 case HostRoot: 23510 var root = parentFiber.stateNode; 23511 root.effectDuration += effectDuration; 23512 break outer; 23513 23514 case Profiler: 23515 var parentStateNode = parentFiber.stateNode; 23516 parentStateNode.effectDuration += effectDuration; 23517 break outer; 23518 } 23519 23520 parentFiber = parentFiber.return; 23521 } 23522 } 23523 } 23524 23525 break; 23526 } 23527 23528 case SuspenseComponent: 23529 { 23530 commitSuspenseHydrationCallbacks(finishedRoot, finishedWork); 23531 break; 23532 } 23533 23534 case SuspenseListComponent: 23535 case IncompleteClassComponent: 23536 case ScopeComponent: 23537 case OffscreenComponent: 23538 case LegacyHiddenComponent: 23539 case TracingMarkerComponent: 23540 { 23541 break; 23542 } 23543 23544 default: 23545 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.'); 23546 } 23547 } 23548 23549 if ( !offscreenSubtreeWasHidden) { 23550 { 23551 if (finishedWork.flags & Ref) { 23552 commitAttachRef(finishedWork); 23553 } 23554 } 23555 } 23556 } 23557 23558 function reappearLayoutEffectsOnFiber(node) { 23559 // Turn on layout effects in a tree that previously disappeared. 23560 // TODO (Offscreen) Check: flags & LayoutStatic 23561 switch (node.tag) { 23562 case FunctionComponent: 23563 case ForwardRef: 23564 case SimpleMemoComponent: 23565 { 23566 if ( node.mode & ProfileMode) { 23567 try { 23568 startLayoutEffectTimer(); 23569 safelyCallCommitHookLayoutEffectListMount(node, node.return); 23570 } finally { 23571 recordLayoutEffectDuration(node); 23572 } 23573 } else { 23574 safelyCallCommitHookLayoutEffectListMount(node, node.return); 23575 } 23576 23577 break; 23578 } 23579 23580 case ClassComponent: 23581 { 23582 var instance = node.stateNode; 23583 23584 if (typeof instance.componentDidMount === 'function') { 23585 safelyCallComponentDidMount(node, node.return, instance); 23586 } 23587 23588 safelyAttachRef(node, node.return); 23589 break; 23590 } 23591 23592 case HostComponent: 23593 { 23594 safelyAttachRef(node, node.return); 23595 break; 23596 } 23597 } 23598 } 23599 23600 function hideOrUnhideAllChildren(finishedWork, isHidden) { 23601 // Only hide or unhide the top-most host nodes. 23602 var hostSubtreeRoot = null; 23603 23604 { 23605 // We only have the top Fiber that was inserted but we need to recurse down its 23606 // children to find all the terminal nodes. 23607 var node = finishedWork; 23608 23609 while (true) { 23610 if (node.tag === HostComponent) { 23611 if (hostSubtreeRoot === null) { 23612 hostSubtreeRoot = node; 23613 23614 try { 23615 var instance = node.stateNode; 23616 23617 if (isHidden) { 23618 hideInstance(instance); 23619 } else { 23620 unhideInstance(node.stateNode, node.memoizedProps); 23621 } 23622 } catch (error) { 23623 captureCommitPhaseError(finishedWork, finishedWork.return, error); 23624 } 23625 } 23626 } else if (node.tag === HostText) { 23627 if (hostSubtreeRoot === null) { 23628 try { 23629 var _instance3 = node.stateNode; 23630 23631 if (isHidden) { 23632 hideTextInstance(_instance3); 23633 } else { 23634 unhideTextInstance(_instance3, node.memoizedProps); 23635 } 23636 } catch (error) { 23637 captureCommitPhaseError(finishedWork, finishedWork.return, error); 23638 } 23639 } 23640 } else if ((node.tag === OffscreenComponent || node.tag === LegacyHiddenComponent) && node.memoizedState !== null && node !== finishedWork) ; else if (node.child !== null) { 23641 node.child.return = node; 23642 node = node.child; 23643 continue; 23644 } 23645 23646 if (node === finishedWork) { 23647 return; 23648 } 23649 23650 while (node.sibling === null) { 23651 if (node.return === null || node.return === finishedWork) { 23652 return; 23653 } 23654 23655 if (hostSubtreeRoot === node) { 23656 hostSubtreeRoot = null; 23657 } 23658 23659 node = node.return; 23660 } 23661 23662 if (hostSubtreeRoot === node) { 23663 hostSubtreeRoot = null; 23664 } 23665 23666 node.sibling.return = node.return; 23667 node = node.sibling; 23668 } 23669 } 23670 } 23671 23672 function commitAttachRef(finishedWork) { 23673 var ref = finishedWork.ref; 23674 23675 if (ref !== null) { 23676 var instance = finishedWork.stateNode; 23677 var instanceToUse; 23678 23679 switch (finishedWork.tag) { 23680 case HostComponent: 23681 instanceToUse = getPublicInstance(instance); 23682 break; 23683 23684 default: 23685 instanceToUse = instance; 23686 } // Moved outside to ensure DCE works with this flag 23687 23688 if (typeof ref === 'function') { 23689 var retVal; 23690 23691 if ( finishedWork.mode & ProfileMode) { 23692 try { 23693 startLayoutEffectTimer(); 23694 retVal = ref(instanceToUse); 23695 } finally { 23696 recordLayoutEffectDuration(finishedWork); 23697 } 23698 } else { 23699 retVal = ref(instanceToUse); 23700 } 23701 23702 { 23703 if (typeof retVal === 'function') { 23704 error('Unexpected return value from a callback ref in %s. ' + 'A callback ref should not return a function.', getComponentNameFromFiber(finishedWork)); 23705 } 23706 } 23707 } else { 23708 { 23709 if (!ref.hasOwnProperty('current')) { 23710 error('Unexpected ref object provided for %s. ' + 'Use either a ref-setter function or React.createRef().', getComponentNameFromFiber(finishedWork)); 23711 } 23712 } 23713 23714 ref.current = instanceToUse; 23715 } 23716 } 23717 } 23718 23719 function detachFiberMutation(fiber) { 23720 // Cut off the return pointer to disconnect it from the tree. 23721 // This enables us to detect and warn against state updates on an unmounted component. 23722 // It also prevents events from bubbling from within disconnected components. 23723 // 23724 // Ideally, we should also clear the child pointer of the parent alternate to let this 23725 // get GC:ed but we don't know which for sure which parent is the current 23726 // one so we'll settle for GC:ing the subtree of this child. 23727 // This child itself will be GC:ed when the parent updates the next time. 23728 // 23729 // Note that we can't clear child or sibling pointers yet. 23730 // They're needed for passive effects and for findDOMNode. 23731 // We defer those fields, and all other cleanup, to the passive phase (see detachFiberAfterEffects). 23732 // 23733 // Don't reset the alternate yet, either. We need that so we can detach the 23734 // alternate's fields in the passive phase. Clearing the return pointer is 23735 // sufficient for findDOMNode semantics. 23736 var alternate = fiber.alternate; 23737 23738 if (alternate !== null) { 23739 alternate.return = null; 23740 } 23741 23742 fiber.return = null; 23743 } 23744 23745 function detachFiberAfterEffects(fiber) { 23746 var alternate = fiber.alternate; 23747 23748 if (alternate !== null) { 23749 fiber.alternate = null; 23750 detachFiberAfterEffects(alternate); 23751 } // Note: Defensively using negation instead of < in case 23752 // `deletedTreeCleanUpLevel` is undefined. 23753 23754 23755 { 23756 // Clear cyclical Fiber fields. This level alone is designed to roughly 23757 // approximate the planned Fiber refactor. In that world, `setState` will be 23758 // bound to a special "instance" object instead of a Fiber. The Instance 23759 // object will not have any of these fields. It will only be connected to 23760 // the fiber tree via a single link at the root. So if this level alone is 23761 // sufficient to fix memory issues, that bodes well for our plans. 23762 fiber.child = null; 23763 fiber.deletions = null; 23764 fiber.sibling = null; // The `stateNode` is cyclical because on host nodes it points to the host 23765 // tree, which has its own pointers to children, parents, and siblings. 23766 // The other host nodes also point back to fibers, so we should detach that 23767 // one, too. 23768 23769 if (fiber.tag === HostComponent) { 23770 var hostInstance = fiber.stateNode; 23771 23772 if (hostInstance !== null) { 23773 detachDeletedInstance(hostInstance); 23774 } 23775 } 23776 23777 fiber.stateNode = null; // I'm intentionally not clearing the `return` field in this level. We 23778 // already disconnect the `return` pointer at the root of the deleted 23779 // subtree (in `detachFiberMutation`). Besides, `return` by itself is not 23780 // cyclical — it's only cyclical when combined with `child`, `sibling`, and 23781 // `alternate`. But we'll clear it in the next level anyway, just in case. 23782 23783 { 23784 fiber._debugOwner = null; 23785 } 23786 23787 { 23788 // Theoretically, nothing in here should be necessary, because we already 23789 // disconnected the fiber from the tree. So even if something leaks this 23790 // particular fiber, it won't leak anything else 23791 // 23792 // The purpose of this branch is to be super aggressive so we can measure 23793 // if there's any difference in memory impact. If there is, that could 23794 // indicate a React leak we don't know about. 23795 fiber.return = null; 23796 fiber.dependencies = null; 23797 fiber.memoizedProps = null; 23798 fiber.memoizedState = null; 23799 fiber.pendingProps = null; 23800 fiber.stateNode = null; // TODO: Move to `commitPassiveUnmountInsideDeletedTreeOnFiber` instead. 23801 23802 fiber.updateQueue = null; 23803 } 23804 } 23805 } 23806 23807 function getHostParentFiber(fiber) { 23808 var parent = fiber.return; 23809 23810 while (parent !== null) { 23811 if (isHostParent(parent)) { 23812 return parent; 23813 } 23814 23815 parent = parent.return; 23816 } 23817 23818 throw new Error('Expected to find a host parent. This error is likely caused by a bug ' + 'in React. Please file an issue.'); 23819 } 23820 23821 function isHostParent(fiber) { 23822 return fiber.tag === HostComponent || fiber.tag === HostRoot || fiber.tag === HostPortal; 23823 } 23824 23825 function getHostSibling(fiber) { 23826 // We're going to search forward into the tree until we find a sibling host 23827 // node. Unfortunately, if multiple insertions are done in a row we have to 23828 // search past them. This leads to exponential search for the next sibling. 23829 // TODO: Find a more efficient way to do this. 23830 var node = fiber; 23831 23832 siblings: while (true) { 23833 // If we didn't find anything, let's try the next sibling. 23834 while (node.sibling === null) { 23835 if (node.return === null || isHostParent(node.return)) { 23836 // If we pop out of the root or hit the parent the fiber we are the 23837 // last sibling. 23838 return null; 23839 } 23840 23841 node = node.return; 23842 } 23843 23844 node.sibling.return = node.return; 23845 node = node.sibling; 23846 23847 while (node.tag !== HostComponent && node.tag !== HostText && node.tag !== DehydratedFragment) { 23848 // If it is not host node and, we might have a host node inside it. 23849 // Try to search down until we find one. 23850 if (node.flags & Placement) { 23851 // If we don't have a child, try the siblings instead. 23852 continue siblings; 23853 } // If we don't have a child, try the siblings instead. 23854 // We also skip portals because they are not part of this host tree. 23855 23856 23857 if (node.child === null || node.tag === HostPortal) { 23858 continue siblings; 23859 } else { 23860 node.child.return = node; 23861 node = node.child; 23862 } 23863 } // Check if this host node is stable or about to be placed. 23864 23865 23866 if (!(node.flags & Placement)) { 23867 // Found it! 23868 return node.stateNode; 23869 } 23870 } 23871 } 23872 23873 function commitPlacement(finishedWork) { 23874 23875 23876 var parentFiber = getHostParentFiber(finishedWork); // Note: these two variables *must* always be updated together. 23877 23878 switch (parentFiber.tag) { 23879 case HostComponent: 23880 { 23881 var parent = parentFiber.stateNode; 23882 23883 if (parentFiber.flags & ContentReset) { 23884 // Reset the text content of the parent before doing any insertions 23885 resetTextContent(parent); // Clear ContentReset from the effect tag 23886 23887 parentFiber.flags &= ~ContentReset; 23888 } 23889 23890 var before = getHostSibling(finishedWork); // We only have the top Fiber that was inserted but we need to recurse down its 23891 // children to find all the terminal nodes. 23892 23893 insertOrAppendPlacementNode(finishedWork, before, parent); 23894 break; 23895 } 23896 23897 case HostRoot: 23898 case HostPortal: 23899 { 23900 var _parent = parentFiber.stateNode.containerInfo; 23901 23902 var _before = getHostSibling(finishedWork); 23903 23904 insertOrAppendPlacementNodeIntoContainer(finishedWork, _before, _parent); 23905 break; 23906 } 23907 // eslint-disable-next-line-no-fallthrough 23908 23909 default: 23910 throw new Error('Invalid host parent fiber. This error is likely caused by a bug ' + 'in React. Please file an issue.'); 23911 } 23912 } 23913 23914 function insertOrAppendPlacementNodeIntoContainer(node, before, parent) { 23915 var tag = node.tag; 23916 var isHost = tag === HostComponent || tag === HostText; 23917 23918 if (isHost) { 23919 var stateNode = node.stateNode; 23920 23921 if (before) { 23922 insertInContainerBefore(parent, stateNode, before); 23923 } else { 23924 appendChildToContainer(parent, stateNode); 23925 } 23926 } else if (tag === HostPortal) ; else { 23927 var child = node.child; 23928 23929 if (child !== null) { 23930 insertOrAppendPlacementNodeIntoContainer(child, before, parent); 23931 var sibling = child.sibling; 23932 23933 while (sibling !== null) { 23934 insertOrAppendPlacementNodeIntoContainer(sibling, before, parent); 23935 sibling = sibling.sibling; 23936 } 23937 } 23938 } 23939 } 23940 23941 function insertOrAppendPlacementNode(node, before, parent) { 23942 var tag = node.tag; 23943 var isHost = tag === HostComponent || tag === HostText; 23944 23945 if (isHost) { 23946 var stateNode = node.stateNode; 23947 23948 if (before) { 23949 insertBefore(parent, stateNode, before); 23950 } else { 23951 appendChild(parent, stateNode); 23952 } 23953 } else if (tag === HostPortal) ; else { 23954 var child = node.child; 23955 23956 if (child !== null) { 23957 insertOrAppendPlacementNode(child, before, parent); 23958 var sibling = child.sibling; 23959 23960 while (sibling !== null) { 23961 insertOrAppendPlacementNode(sibling, before, parent); 23962 sibling = sibling.sibling; 23963 } 23964 } 23965 } 23966 } // These are tracked on the stack as we recursively traverse a 23967 // deleted subtree. 23968 // TODO: Update these during the whole mutation phase, not just during 23969 // a deletion. 23970 23971 23972 var hostParent = null; 23973 var hostParentIsContainer = false; 23974 23975 function commitDeletionEffects(root, returnFiber, deletedFiber) { 23976 { 23977 // We only have the top Fiber that was deleted but we need to recurse down its 23978 // children to find all the terminal nodes. 23979 // Recursively delete all host nodes from the parent, detach refs, clean 23980 // up mounted layout effects, and call componentWillUnmount. 23981 // We only need to remove the topmost host child in each branch. But then we 23982 // still need to keep traversing to unmount effects, refs, and cWU. TODO: We 23983 // could split this into two separate traversals functions, where the second 23984 // one doesn't include any removeChild logic. This is maybe the same 23985 // function as "disappearLayoutEffects" (or whatever that turns into after 23986 // the layout phase is refactored to use recursion). 23987 // Before starting, find the nearest host parent on the stack so we know 23988 // which instance/container to remove the children from. 23989 // TODO: Instead of searching up the fiber return path on every deletion, we 23990 // can track the nearest host component on the JS stack as we traverse the 23991 // tree during the commit phase. This would make insertions faster, too. 23992 var parent = returnFiber; 23993 23994 findParent: while (parent !== null) { 23995 switch (parent.tag) { 23996 case HostComponent: 23997 { 23998 hostParent = parent.stateNode; 23999 hostParentIsContainer = false; 24000 break findParent; 24001 } 24002 24003 case HostRoot: 24004 { 24005 hostParent = parent.stateNode.containerInfo; 24006 hostParentIsContainer = true; 24007 break findParent; 24008 } 24009 24010 case HostPortal: 24011 { 24012 hostParent = parent.stateNode.containerInfo; 24013 hostParentIsContainer = true; 24014 break findParent; 24015 } 24016 } 24017 24018 parent = parent.return; 24019 } 24020 24021 if (hostParent === null) { 24022 throw new Error('Expected to find a host parent. This error is likely caused by ' + 'a bug in React. Please file an issue.'); 24023 } 24024 24025 commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber); 24026 hostParent = null; 24027 hostParentIsContainer = false; 24028 } 24029 24030 detachFiberMutation(deletedFiber); 24031 } 24032 24033 function recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, parent) { 24034 // TODO: Use a static flag to skip trees that don't have unmount effects 24035 var child = parent.child; 24036 24037 while (child !== null) { 24038 commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, child); 24039 child = child.sibling; 24040 } 24041 } 24042 24043 function commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, deletedFiber) { 24044 onCommitUnmount(deletedFiber); // The cases in this outer switch modify the stack before they traverse 24045 // into their subtree. There are simpler cases in the inner switch 24046 // that don't modify the stack. 24047 24048 switch (deletedFiber.tag) { 24049 case HostComponent: 24050 { 24051 if (!offscreenSubtreeWasHidden) { 24052 safelyDetachRef(deletedFiber, nearestMountedAncestor); 24053 } // Intentional fallthrough to next branch 24054 24055 } 24056 // eslint-disable-next-line-no-fallthrough 24057 24058 case HostText: 24059 { 24060 // We only need to remove the nearest host child. Set the host parent 24061 // to `null` on the stack to indicate that nested children don't 24062 // need to be removed. 24063 { 24064 var prevHostParent = hostParent; 24065 var prevHostParentIsContainer = hostParentIsContainer; 24066 hostParent = null; 24067 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24068 hostParent = prevHostParent; 24069 hostParentIsContainer = prevHostParentIsContainer; 24070 24071 if (hostParent !== null) { 24072 // Now that all the child effects have unmounted, we can remove the 24073 // node from the tree. 24074 if (hostParentIsContainer) { 24075 removeChildFromContainer(hostParent, deletedFiber.stateNode); 24076 } else { 24077 removeChild(hostParent, deletedFiber.stateNode); 24078 } 24079 } 24080 } 24081 24082 return; 24083 } 24084 24085 case DehydratedFragment: 24086 { 24087 // Delete the dehydrated suspense boundary and all of its content. 24088 24089 24090 { 24091 if (hostParent !== null) { 24092 if (hostParentIsContainer) { 24093 clearSuspenseBoundaryFromContainer(hostParent, deletedFiber.stateNode); 24094 } else { 24095 clearSuspenseBoundary(hostParent, deletedFiber.stateNode); 24096 } 24097 } 24098 } 24099 24100 return; 24101 } 24102 24103 case HostPortal: 24104 { 24105 { 24106 // When we go into a portal, it becomes the parent to remove from. 24107 var _prevHostParent = hostParent; 24108 var _prevHostParentIsContainer = hostParentIsContainer; 24109 hostParent = deletedFiber.stateNode.containerInfo; 24110 hostParentIsContainer = true; 24111 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24112 hostParent = _prevHostParent; 24113 hostParentIsContainer = _prevHostParentIsContainer; 24114 } 24115 24116 return; 24117 } 24118 24119 case FunctionComponent: 24120 case ForwardRef: 24121 case MemoComponent: 24122 case SimpleMemoComponent: 24123 { 24124 if (!offscreenSubtreeWasHidden) { 24125 var updateQueue = deletedFiber.updateQueue; 24126 24127 if (updateQueue !== null) { 24128 var lastEffect = updateQueue.lastEffect; 24129 24130 if (lastEffect !== null) { 24131 var firstEffect = lastEffect.next; 24132 var effect = firstEffect; 24133 24134 do { 24135 var _effect = effect, 24136 destroy = _effect.destroy, 24137 tag = _effect.tag; 24138 24139 if (destroy !== undefined) { 24140 if ((tag & Insertion) !== NoFlags$1) { 24141 safelyCallDestroy(deletedFiber, nearestMountedAncestor, destroy); 24142 } else if ((tag & Layout) !== NoFlags$1) { 24143 { 24144 markComponentLayoutEffectUnmountStarted(deletedFiber); 24145 } 24146 24147 if ( deletedFiber.mode & ProfileMode) { 24148 startLayoutEffectTimer(); 24149 safelyCallDestroy(deletedFiber, nearestMountedAncestor, destroy); 24150 recordLayoutEffectDuration(deletedFiber); 24151 } else { 24152 safelyCallDestroy(deletedFiber, nearestMountedAncestor, destroy); 24153 } 24154 24155 { 24156 markComponentLayoutEffectUnmountStopped(); 24157 } 24158 } 24159 } 24160 24161 effect = effect.next; 24162 } while (effect !== firstEffect); 24163 } 24164 } 24165 } 24166 24167 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24168 return; 24169 } 24170 24171 case ClassComponent: 24172 { 24173 if (!offscreenSubtreeWasHidden) { 24174 safelyDetachRef(deletedFiber, nearestMountedAncestor); 24175 var instance = deletedFiber.stateNode; 24176 24177 if (typeof instance.componentWillUnmount === 'function') { 24178 safelyCallComponentWillUnmount(deletedFiber, nearestMountedAncestor, instance); 24179 } 24180 } 24181 24182 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24183 return; 24184 } 24185 24186 case ScopeComponent: 24187 { 24188 24189 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24190 return; 24191 } 24192 24193 case OffscreenComponent: 24194 { 24195 if ( // TODO: Remove this dead flag 24196 deletedFiber.mode & ConcurrentMode) { 24197 // If this offscreen component is hidden, we already unmounted it. Before 24198 // deleting the children, track that it's already unmounted so that we 24199 // don't attempt to unmount the effects again. 24200 // TODO: If the tree is hidden, in most cases we should be able to skip 24201 // over the nested children entirely. An exception is we haven't yet found 24202 // the topmost host node to delete, which we already track on the stack. 24203 // But the other case is portals, which need to be detached no matter how 24204 // deeply they are nested. We should use a subtree flag to track whether a 24205 // subtree includes a nested portal. 24206 var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; 24207 offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden || deletedFiber.memoizedState !== null; 24208 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24209 offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; 24210 } else { 24211 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24212 } 24213 24214 break; 24215 } 24216 24217 default: 24218 { 24219 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24220 return; 24221 } 24222 } 24223 } 24224 24225 function commitSuspenseCallback(finishedWork) { 24226 // TODO: Move this to passive phase 24227 var newState = finishedWork.memoizedState; 24228 } 24229 24230 function commitSuspenseHydrationCallbacks(finishedRoot, finishedWork) { 24231 24232 var newState = finishedWork.memoizedState; 24233 24234 if (newState === null) { 24235 var current = finishedWork.alternate; 24236 24237 if (current !== null) { 24238 var prevState = current.memoizedState; 24239 24240 if (prevState !== null) { 24241 var suspenseInstance = prevState.dehydrated; 24242 24243 if (suspenseInstance !== null) { 24244 commitHydratedSuspenseInstance(suspenseInstance); 24245 } 24246 } 24247 } 24248 } 24249 } 24250 24251 function attachSuspenseRetryListeners(finishedWork) { 24252 // If this boundary just timed out, then it will have a set of wakeables. 24253 // For each wakeable, attach a listener so that when it resolves, React 24254 // attempts to re-render the boundary in the primary (pre-timeout) state. 24255 var wakeables = finishedWork.updateQueue; 24256 24257 if (wakeables !== null) { 24258 finishedWork.updateQueue = null; 24259 var retryCache = finishedWork.stateNode; 24260 24261 if (retryCache === null) { 24262 retryCache = finishedWork.stateNode = new PossiblyWeakSet(); 24263 } 24264 24265 wakeables.forEach(function (wakeable) { 24266 // Memoize using the boundary fiber to prevent redundant listeners. 24267 var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); 24268 24269 if (!retryCache.has(wakeable)) { 24270 retryCache.add(wakeable); 24271 24272 { 24273 if (isDevToolsPresent) { 24274 if (inProgressLanes !== null && inProgressRoot !== null) { 24275 // If we have pending work still, associate the original updaters with it. 24276 restorePendingUpdaters(inProgressRoot, inProgressLanes); 24277 } else { 24278 throw Error('Expected finished root and lanes to be set. This is a bug in React.'); 24279 } 24280 } 24281 } 24282 24283 wakeable.then(retry, retry); 24284 } 24285 }); 24286 } 24287 } // This function detects when a Suspense boundary goes from visible to hidden. 24288 function commitMutationEffects(root, finishedWork, committedLanes) { 24289 inProgressLanes = committedLanes; 24290 inProgressRoot = root; 24291 setCurrentFiber(finishedWork); 24292 commitMutationEffectsOnFiber(finishedWork, root); 24293 setCurrentFiber(finishedWork); 24294 inProgressLanes = null; 24295 inProgressRoot = null; 24296 } 24297 24298 function recursivelyTraverseMutationEffects(root, parentFiber, lanes) { 24299 // Deletions effects can be scheduled on any fiber type. They need to happen 24300 // before the children effects hae fired. 24301 var deletions = parentFiber.deletions; 24302 24303 if (deletions !== null) { 24304 for (var i = 0; i < deletions.length; i++) { 24305 var childToDelete = deletions[i]; 24306 24307 try { 24308 commitDeletionEffects(root, parentFiber, childToDelete); 24309 } catch (error) { 24310 captureCommitPhaseError(childToDelete, parentFiber, error); 24311 } 24312 } 24313 } 24314 24315 var prevDebugFiber = getCurrentFiber(); 24316 24317 if (parentFiber.subtreeFlags & MutationMask) { 24318 var child = parentFiber.child; 24319 24320 while (child !== null) { 24321 setCurrentFiber(child); 24322 commitMutationEffectsOnFiber(child, root); 24323 child = child.sibling; 24324 } 24325 } 24326 24327 setCurrentFiber(prevDebugFiber); 24328 } 24329 24330 function commitMutationEffectsOnFiber(finishedWork, root, lanes) { 24331 var current = finishedWork.alternate; 24332 var flags = finishedWork.flags; // The effect flag should be checked *after* we refine the type of fiber, 24333 // because the fiber tag is more specific. An exception is any flag related 24334 // to reconcilation, because those can be set on all fiber types. 24335 24336 switch (finishedWork.tag) { 24337 case FunctionComponent: 24338 case ForwardRef: 24339 case MemoComponent: 24340 case SimpleMemoComponent: 24341 { 24342 recursivelyTraverseMutationEffects(root, finishedWork); 24343 commitReconciliationEffects(finishedWork); 24344 24345 if (flags & Update) { 24346 try { 24347 commitHookEffectListUnmount(Insertion | HasEffect, finishedWork, finishedWork.return); 24348 commitHookEffectListMount(Insertion | HasEffect, finishedWork); 24349 } catch (error) { 24350 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24351 } // Layout effects are destroyed during the mutation phase so that all 24352 // destroy functions for all fibers are called before any create functions. 24353 // This prevents sibling component effects from interfering with each other, 24354 // e.g. a destroy function in one component should never override a ref set 24355 // by a create function in another component during the same commit. 24356 24357 24358 if ( finishedWork.mode & ProfileMode) { 24359 try { 24360 startLayoutEffectTimer(); 24361 commitHookEffectListUnmount(Layout | HasEffect, finishedWork, finishedWork.return); 24362 } catch (error) { 24363 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24364 } 24365 24366 recordLayoutEffectDuration(finishedWork); 24367 } else { 24368 try { 24369 commitHookEffectListUnmount(Layout | HasEffect, finishedWork, finishedWork.return); 24370 } catch (error) { 24371 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24372 } 24373 } 24374 } 24375 24376 return; 24377 } 24378 24379 case ClassComponent: 24380 { 24381 recursivelyTraverseMutationEffects(root, finishedWork); 24382 commitReconciliationEffects(finishedWork); 24383 24384 if (flags & Ref) { 24385 if (current !== null) { 24386 safelyDetachRef(current, current.return); 24387 } 24388 } 24389 24390 return; 24391 } 24392 24393 case HostComponent: 24394 { 24395 recursivelyTraverseMutationEffects(root, finishedWork); 24396 commitReconciliationEffects(finishedWork); 24397 24398 if (flags & Ref) { 24399 if (current !== null) { 24400 safelyDetachRef(current, current.return); 24401 } 24402 } 24403 24404 { 24405 // TODO: ContentReset gets cleared by the children during the commit 24406 // phase. This is a refactor hazard because it means we must read 24407 // flags the flags after `commitReconciliationEffects` has already run; 24408 // the order matters. We should refactor so that ContentReset does not 24409 // rely on mutating the flag during commit. Like by setting a flag 24410 // during the render phase instead. 24411 if (finishedWork.flags & ContentReset) { 24412 var instance = finishedWork.stateNode; 24413 24414 try { 24415 resetTextContent(instance); 24416 } catch (error) { 24417 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24418 } 24419 } 24420 24421 if (flags & Update) { 24422 var _instance4 = finishedWork.stateNode; 24423 24424 if (_instance4 != null) { 24425 // Commit the work prepared earlier. 24426 var newProps = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps 24427 // as the newProps. The updatePayload will contain the real change in 24428 // this case. 24429 24430 var oldProps = current !== null ? current.memoizedProps : newProps; 24431 var type = finishedWork.type; // TODO: Type the updateQueue to be specific to host components. 24432 24433 var updatePayload = finishedWork.updateQueue; 24434 finishedWork.updateQueue = null; 24435 24436 if (updatePayload !== null) { 24437 try { 24438 commitUpdate(_instance4, updatePayload, type, oldProps, newProps, finishedWork); 24439 } catch (error) { 24440 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24441 } 24442 } 24443 } 24444 } 24445 } 24446 24447 return; 24448 } 24449 24450 case HostText: 24451 { 24452 recursivelyTraverseMutationEffects(root, finishedWork); 24453 commitReconciliationEffects(finishedWork); 24454 24455 if (flags & Update) { 24456 { 24457 if (finishedWork.stateNode === null) { 24458 throw new Error('This should have a text node initialized. This error is likely ' + 'caused by a bug in React. Please file an issue.'); 24459 } 24460 24461 var textInstance = finishedWork.stateNode; 24462 var newText = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps 24463 // as the newProps. The updatePayload will contain the real change in 24464 // this case. 24465 24466 var oldText = current !== null ? current.memoizedProps : newText; 24467 24468 try { 24469 commitTextUpdate(textInstance, oldText, newText); 24470 } catch (error) { 24471 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24472 } 24473 } 24474 } 24475 24476 return; 24477 } 24478 24479 case HostRoot: 24480 { 24481 recursivelyTraverseMutationEffects(root, finishedWork); 24482 commitReconciliationEffects(finishedWork); 24483 24484 if (flags & Update) { 24485 { 24486 if (current !== null) { 24487 var prevRootState = current.memoizedState; 24488 24489 if (prevRootState.isDehydrated) { 24490 try { 24491 commitHydratedContainer(root.containerInfo); 24492 } catch (error) { 24493 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24494 } 24495 } 24496 } 24497 } 24498 } 24499 24500 return; 24501 } 24502 24503 case HostPortal: 24504 { 24505 recursivelyTraverseMutationEffects(root, finishedWork); 24506 commitReconciliationEffects(finishedWork); 24507 24508 return; 24509 } 24510 24511 case SuspenseComponent: 24512 { 24513 recursivelyTraverseMutationEffects(root, finishedWork); 24514 commitReconciliationEffects(finishedWork); 24515 var offscreenFiber = finishedWork.child; 24516 24517 if (offscreenFiber.flags & Visibility) { 24518 var offscreenInstance = offscreenFiber.stateNode; 24519 var newState = offscreenFiber.memoizedState; 24520 var isHidden = newState !== null; // Track the current state on the Offscreen instance so we can 24521 // read it during an event 24522 24523 offscreenInstance.isHidden = isHidden; 24524 24525 if (isHidden) { 24526 var wasHidden = offscreenFiber.alternate !== null && offscreenFiber.alternate.memoizedState !== null; 24527 24528 if (!wasHidden) { 24529 // TODO: Move to passive phase 24530 markCommitTimeOfFallback(); 24531 } 24532 } 24533 } 24534 24535 if (flags & Update) { 24536 try { 24537 commitSuspenseCallback(finishedWork); 24538 } catch (error) { 24539 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24540 } 24541 24542 attachSuspenseRetryListeners(finishedWork); 24543 } 24544 24545 return; 24546 } 24547 24548 case OffscreenComponent: 24549 { 24550 var _wasHidden = current !== null && current.memoizedState !== null; 24551 24552 if ( // TODO: Remove this dead flag 24553 finishedWork.mode & ConcurrentMode) { 24554 // Before committing the children, track on the stack whether this 24555 // offscreen subtree was already hidden, so that we don't unmount the 24556 // effects again. 24557 var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; 24558 offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden || _wasHidden; 24559 recursivelyTraverseMutationEffects(root, finishedWork); 24560 offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; 24561 } else { 24562 recursivelyTraverseMutationEffects(root, finishedWork); 24563 } 24564 24565 commitReconciliationEffects(finishedWork); 24566 24567 if (flags & Visibility) { 24568 var _offscreenInstance = finishedWork.stateNode; 24569 var _newState = finishedWork.memoizedState; 24570 24571 var _isHidden = _newState !== null; 24572 24573 var offscreenBoundary = finishedWork; // Track the current state on the Offscreen instance so we can 24574 // read it during an event 24575 24576 _offscreenInstance.isHidden = _isHidden; 24577 24578 { 24579 if (_isHidden) { 24580 if (!_wasHidden) { 24581 if ((offscreenBoundary.mode & ConcurrentMode) !== NoMode) { 24582 nextEffect = offscreenBoundary; 24583 var offscreenChild = offscreenBoundary.child; 24584 24585 while (offscreenChild !== null) { 24586 nextEffect = offscreenChild; 24587 disappearLayoutEffects_begin(offscreenChild); 24588 offscreenChild = offscreenChild.sibling; 24589 } 24590 } 24591 } 24592 } 24593 } 24594 24595 { 24596 // TODO: This needs to run whenever there's an insertion or update 24597 // inside a hidden Offscreen tree. 24598 hideOrUnhideAllChildren(offscreenBoundary, _isHidden); 24599 } 24600 } 24601 24602 return; 24603 } 24604 24605 case SuspenseListComponent: 24606 { 24607 recursivelyTraverseMutationEffects(root, finishedWork); 24608 commitReconciliationEffects(finishedWork); 24609 24610 if (flags & Update) { 24611 attachSuspenseRetryListeners(finishedWork); 24612 } 24613 24614 return; 24615 } 24616 24617 case ScopeComponent: 24618 { 24619 24620 return; 24621 } 24622 24623 default: 24624 { 24625 recursivelyTraverseMutationEffects(root, finishedWork); 24626 commitReconciliationEffects(finishedWork); 24627 return; 24628 } 24629 } 24630 } 24631 24632 function commitReconciliationEffects(finishedWork) { 24633 // Placement effects (insertions, reorders) can be scheduled on any fiber 24634 // type. They needs to happen after the children effects have fired, but 24635 // before the effects on this fiber have fired. 24636 var flags = finishedWork.flags; 24637 24638 if (flags & Placement) { 24639 try { 24640 commitPlacement(finishedWork); 24641 } catch (error) { 24642 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24643 } // Clear the "placement" from effect tag so that we know that this is 24644 // inserted, before any life-cycles like componentDidMount gets called. 24645 // TODO: findDOMNode doesn't rely on this any more but isMounted does 24646 // and isMounted is deprecated anyway so we should be able to kill this. 24647 24648 24649 finishedWork.flags &= ~Placement; 24650 } 24651 24652 if (flags & Hydrating) { 24653 finishedWork.flags &= ~Hydrating; 24654 } 24655 } 24656 24657 function commitLayoutEffects(finishedWork, root, committedLanes) { 24658 inProgressLanes = committedLanes; 24659 inProgressRoot = root; 24660 nextEffect = finishedWork; 24661 commitLayoutEffects_begin(finishedWork, root, committedLanes); 24662 inProgressLanes = null; 24663 inProgressRoot = null; 24664 } 24665 24666 function commitLayoutEffects_begin(subtreeRoot, root, committedLanes) { 24667 // Suspense layout effects semantics don't change for legacy roots. 24668 var isModernRoot = (subtreeRoot.mode & ConcurrentMode) !== NoMode; 24669 24670 while (nextEffect !== null) { 24671 var fiber = nextEffect; 24672 var firstChild = fiber.child; 24673 24674 if ( fiber.tag === OffscreenComponent && isModernRoot) { 24675 // Keep track of the current Offscreen stack's state. 24676 var isHidden = fiber.memoizedState !== null; 24677 var newOffscreenSubtreeIsHidden = isHidden || offscreenSubtreeIsHidden; 24678 24679 if (newOffscreenSubtreeIsHidden) { 24680 // The Offscreen tree is hidden. Skip over its layout effects. 24681 commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes); 24682 continue; 24683 } else { 24684 // TODO (Offscreen) Also check: subtreeFlags & LayoutMask 24685 var current = fiber.alternate; 24686 var wasHidden = current !== null && current.memoizedState !== null; 24687 var newOffscreenSubtreeWasHidden = wasHidden || offscreenSubtreeWasHidden; 24688 var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden; 24689 var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; // Traverse the Offscreen subtree with the current Offscreen as the root. 24690 24691 offscreenSubtreeIsHidden = newOffscreenSubtreeIsHidden; 24692 offscreenSubtreeWasHidden = newOffscreenSubtreeWasHidden; 24693 24694 if (offscreenSubtreeWasHidden && !prevOffscreenSubtreeWasHidden) { 24695 // This is the root of a reappearing boundary. Turn its layout effects 24696 // back on. 24697 nextEffect = fiber; 24698 reappearLayoutEffects_begin(fiber); 24699 } 24700 24701 var child = firstChild; 24702 24703 while (child !== null) { 24704 nextEffect = child; 24705 commitLayoutEffects_begin(child, // New root; bubble back up to here and stop. 24706 root, committedLanes); 24707 child = child.sibling; 24708 } // Restore Offscreen state and resume in our-progress traversal. 24709 24710 24711 nextEffect = fiber; 24712 offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; 24713 offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; 24714 commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes); 24715 continue; 24716 } 24717 } 24718 24719 if ((fiber.subtreeFlags & LayoutMask) !== NoFlags && firstChild !== null) { 24720 firstChild.return = fiber; 24721 nextEffect = firstChild; 24722 } else { 24723 commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes); 24724 } 24725 } 24726 } 24727 24728 function commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes) { 24729 while (nextEffect !== null) { 24730 var fiber = nextEffect; 24731 24732 if ((fiber.flags & LayoutMask) !== NoFlags) { 24733 var current = fiber.alternate; 24734 setCurrentFiber(fiber); 24735 24736 try { 24737 commitLayoutEffectOnFiber(root, current, fiber, committedLanes); 24738 } catch (error) { 24739 captureCommitPhaseError(fiber, fiber.return, error); 24740 } 24741 24742 resetCurrentFiber(); 24743 } 24744 24745 if (fiber === subtreeRoot) { 24746 nextEffect = null; 24747 return; 24748 } 24749 24750 var sibling = fiber.sibling; 24751 24752 if (sibling !== null) { 24753 sibling.return = fiber.return; 24754 nextEffect = sibling; 24755 return; 24756 } 24757 24758 nextEffect = fiber.return; 24759 } 24760 } 24761 24762 function disappearLayoutEffects_begin(subtreeRoot) { 24763 while (nextEffect !== null) { 24764 var fiber = nextEffect; 24765 var firstChild = fiber.child; // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) 24766 24767 switch (fiber.tag) { 24768 case FunctionComponent: 24769 case ForwardRef: 24770 case MemoComponent: 24771 case SimpleMemoComponent: 24772 { 24773 if ( fiber.mode & ProfileMode) { 24774 try { 24775 startLayoutEffectTimer(); 24776 commitHookEffectListUnmount(Layout, fiber, fiber.return); 24777 } finally { 24778 recordLayoutEffectDuration(fiber); 24779 } 24780 } else { 24781 commitHookEffectListUnmount(Layout, fiber, fiber.return); 24782 } 24783 24784 break; 24785 } 24786 24787 case ClassComponent: 24788 { 24789 // TODO (Offscreen) Check: flags & RefStatic 24790 safelyDetachRef(fiber, fiber.return); 24791 var instance = fiber.stateNode; 24792 24793 if (typeof instance.componentWillUnmount === 'function') { 24794 safelyCallComponentWillUnmount(fiber, fiber.return, instance); 24795 } 24796 24797 break; 24798 } 24799 24800 case HostComponent: 24801 { 24802 safelyDetachRef(fiber, fiber.return); 24803 break; 24804 } 24805 24806 case OffscreenComponent: 24807 { 24808 // Check if this is a 24809 var isHidden = fiber.memoizedState !== null; 24810 24811 if (isHidden) { 24812 // Nested Offscreen tree is already hidden. Don't disappear 24813 // its effects. 24814 disappearLayoutEffects_complete(subtreeRoot); 24815 continue; 24816 } 24817 24818 break; 24819 } 24820 } // TODO (Offscreen) Check: subtreeFlags & LayoutStatic 24821 24822 24823 if (firstChild !== null) { 24824 firstChild.return = fiber; 24825 nextEffect = firstChild; 24826 } else { 24827 disappearLayoutEffects_complete(subtreeRoot); 24828 } 24829 } 24830 } 24831 24832 function disappearLayoutEffects_complete(subtreeRoot) { 24833 while (nextEffect !== null) { 24834 var fiber = nextEffect; 24835 24836 if (fiber === subtreeRoot) { 24837 nextEffect = null; 24838 return; 24839 } 24840 24841 var sibling = fiber.sibling; 24842 24843 if (sibling !== null) { 24844 sibling.return = fiber.return; 24845 nextEffect = sibling; 24846 return; 24847 } 24848 24849 nextEffect = fiber.return; 24850 } 24851 } 24852 24853 function reappearLayoutEffects_begin(subtreeRoot) { 24854 while (nextEffect !== null) { 24855 var fiber = nextEffect; 24856 var firstChild = fiber.child; 24857 24858 if (fiber.tag === OffscreenComponent) { 24859 var isHidden = fiber.memoizedState !== null; 24860 24861 if (isHidden) { 24862 // Nested Offscreen tree is still hidden. Don't re-appear its effects. 24863 reappearLayoutEffects_complete(subtreeRoot); 24864 continue; 24865 } 24866 } // TODO (Offscreen) Check: subtreeFlags & LayoutStatic 24867 24868 24869 if (firstChild !== null) { 24870 // This node may have been reused from a previous render, so we can't 24871 // assume its return pointer is correct. 24872 firstChild.return = fiber; 24873 nextEffect = firstChild; 24874 } else { 24875 reappearLayoutEffects_complete(subtreeRoot); 24876 } 24877 } 24878 } 24879 24880 function reappearLayoutEffects_complete(subtreeRoot) { 24881 while (nextEffect !== null) { 24882 var fiber = nextEffect; // TODO (Offscreen) Check: flags & LayoutStatic 24883 24884 setCurrentFiber(fiber); 24885 24886 try { 24887 reappearLayoutEffectsOnFiber(fiber); 24888 } catch (error) { 24889 captureCommitPhaseError(fiber, fiber.return, error); 24890 } 24891 24892 resetCurrentFiber(); 24893 24894 if (fiber === subtreeRoot) { 24895 nextEffect = null; 24896 return; 24897 } 24898 24899 var sibling = fiber.sibling; 24900 24901 if (sibling !== null) { 24902 // This node may have been reused from a previous render, so we can't 24903 // assume its return pointer is correct. 24904 sibling.return = fiber.return; 24905 nextEffect = sibling; 24906 return; 24907 } 24908 24909 nextEffect = fiber.return; 24910 } 24911 } 24912 24913 function commitPassiveMountEffects(root, finishedWork, committedLanes, committedTransitions) { 24914 nextEffect = finishedWork; 24915 commitPassiveMountEffects_begin(finishedWork, root, committedLanes, committedTransitions); 24916 } 24917 24918 function commitPassiveMountEffects_begin(subtreeRoot, root, committedLanes, committedTransitions) { 24919 while (nextEffect !== null) { 24920 var fiber = nextEffect; 24921 var firstChild = fiber.child; 24922 24923 if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) { 24924 firstChild.return = fiber; 24925 nextEffect = firstChild; 24926 } else { 24927 commitPassiveMountEffects_complete(subtreeRoot, root, committedLanes, committedTransitions); 24928 } 24929 } 24930 } 24931 24932 function commitPassiveMountEffects_complete(subtreeRoot, root, committedLanes, committedTransitions) { 24933 while (nextEffect !== null) { 24934 var fiber = nextEffect; 24935 24936 if ((fiber.flags & Passive) !== NoFlags) { 24937 setCurrentFiber(fiber); 24938 24939 try { 24940 commitPassiveMountOnFiber(root, fiber, committedLanes, committedTransitions); 24941 } catch (error) { 24942 captureCommitPhaseError(fiber, fiber.return, error); 24943 } 24944 24945 resetCurrentFiber(); 24946 } 24947 24948 if (fiber === subtreeRoot) { 24949 nextEffect = null; 24950 return; 24951 } 24952 24953 var sibling = fiber.sibling; 24954 24955 if (sibling !== null) { 24956 sibling.return = fiber.return; 24957 nextEffect = sibling; 24958 return; 24959 } 24960 24961 nextEffect = fiber.return; 24962 } 24963 } 24964 24965 function commitPassiveMountOnFiber(finishedRoot, finishedWork, committedLanes, committedTransitions) { 24966 switch (finishedWork.tag) { 24967 case FunctionComponent: 24968 case ForwardRef: 24969 case SimpleMemoComponent: 24970 { 24971 if ( finishedWork.mode & ProfileMode) { 24972 startPassiveEffectTimer(); 24973 24974 try { 24975 commitHookEffectListMount(Passive$1 | HasEffect, finishedWork); 24976 } finally { 24977 recordPassiveEffectDuration(finishedWork); 24978 } 24979 } else { 24980 commitHookEffectListMount(Passive$1 | HasEffect, finishedWork); 24981 } 24982 24983 break; 24984 } 24985 } 24986 } 24987 24988 function commitPassiveUnmountEffects(firstChild) { 24989 nextEffect = firstChild; 24990 commitPassiveUnmountEffects_begin(); 24991 } 24992 24993 function commitPassiveUnmountEffects_begin() { 24994 while (nextEffect !== null) { 24995 var fiber = nextEffect; 24996 var child = fiber.child; 24997 24998 if ((nextEffect.flags & ChildDeletion) !== NoFlags) { 24999 var deletions = fiber.deletions; 25000 25001 if (deletions !== null) { 25002 for (var i = 0; i < deletions.length; i++) { 25003 var fiberToDelete = deletions[i]; 25004 nextEffect = fiberToDelete; 25005 commitPassiveUnmountEffectsInsideOfDeletedTree_begin(fiberToDelete, fiber); 25006 } 25007 25008 { 25009 // A fiber was deleted from this parent fiber, but it's still part of 25010 // the previous (alternate) parent fiber's list of children. Because 25011 // children are a linked list, an earlier sibling that's still alive 25012 // will be connected to the deleted fiber via its `alternate`: 25013 // 25014 // live fiber 25015 // --alternate--> previous live fiber 25016 // --sibling--> deleted fiber 25017 // 25018 // We can't disconnect `alternate` on nodes that haven't been deleted 25019 // yet, but we can disconnect the `sibling` and `child` pointers. 25020 var previousFiber = fiber.alternate; 25021 25022 if (previousFiber !== null) { 25023 var detachedChild = previousFiber.child; 25024 25025 if (detachedChild !== null) { 25026 previousFiber.child = null; 25027 25028 do { 25029 var detachedSibling = detachedChild.sibling; 25030 detachedChild.sibling = null; 25031 detachedChild = detachedSibling; 25032 } while (detachedChild !== null); 25033 } 25034 } 25035 } 25036 25037 nextEffect = fiber; 25038 } 25039 } 25040 25041 if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && child !== null) { 25042 child.return = fiber; 25043 nextEffect = child; 25044 } else { 25045 commitPassiveUnmountEffects_complete(); 25046 } 25047 } 25048 } 25049 25050 function commitPassiveUnmountEffects_complete() { 25051 while (nextEffect !== null) { 25052 var fiber = nextEffect; 25053 25054 if ((fiber.flags & Passive) !== NoFlags) { 25055 setCurrentFiber(fiber); 25056 commitPassiveUnmountOnFiber(fiber); 25057 resetCurrentFiber(); 25058 } 25059 25060 var sibling = fiber.sibling; 25061 25062 if (sibling !== null) { 25063 sibling.return = fiber.return; 25064 nextEffect = sibling; 25065 return; 25066 } 25067 25068 nextEffect = fiber.return; 25069 } 25070 } 25071 25072 function commitPassiveUnmountOnFiber(finishedWork) { 25073 switch (finishedWork.tag) { 25074 case FunctionComponent: 25075 case ForwardRef: 25076 case SimpleMemoComponent: 25077 { 25078 if ( finishedWork.mode & ProfileMode) { 25079 startPassiveEffectTimer(); 25080 commitHookEffectListUnmount(Passive$1 | HasEffect, finishedWork, finishedWork.return); 25081 recordPassiveEffectDuration(finishedWork); 25082 } else { 25083 commitHookEffectListUnmount(Passive$1 | HasEffect, finishedWork, finishedWork.return); 25084 } 25085 25086 break; 25087 } 25088 } 25089 } 25090 25091 function commitPassiveUnmountEffectsInsideOfDeletedTree_begin(deletedSubtreeRoot, nearestMountedAncestor) { 25092 while (nextEffect !== null) { 25093 var fiber = nextEffect; // Deletion effects fire in parent -> child order 25094 // TODO: Check if fiber has a PassiveStatic flag 25095 25096 setCurrentFiber(fiber); 25097 commitPassiveUnmountInsideDeletedTreeOnFiber(fiber, nearestMountedAncestor); 25098 resetCurrentFiber(); 25099 var child = fiber.child; // TODO: Only traverse subtree if it has a PassiveStatic flag. (But, if we 25100 // do this, still need to handle `deletedTreeCleanUpLevel` correctly.) 25101 25102 if (child !== null) { 25103 child.return = fiber; 25104 nextEffect = child; 25105 } else { 25106 commitPassiveUnmountEffectsInsideOfDeletedTree_complete(deletedSubtreeRoot); 25107 } 25108 } 25109 } 25110 25111 function commitPassiveUnmountEffectsInsideOfDeletedTree_complete(deletedSubtreeRoot) { 25112 while (nextEffect !== null) { 25113 var fiber = nextEffect; 25114 var sibling = fiber.sibling; 25115 var returnFiber = fiber.return; 25116 25117 { 25118 // Recursively traverse the entire deleted tree and clean up fiber fields. 25119 // This is more aggressive than ideal, and the long term goal is to only 25120 // have to detach the deleted tree at the root. 25121 detachFiberAfterEffects(fiber); 25122 25123 if (fiber === deletedSubtreeRoot) { 25124 nextEffect = null; 25125 return; 25126 } 25127 } 25128 25129 if (sibling !== null) { 25130 sibling.return = returnFiber; 25131 nextEffect = sibling; 25132 return; 25133 } 25134 25135 nextEffect = returnFiber; 25136 } 25137 } 25138 25139 function commitPassiveUnmountInsideDeletedTreeOnFiber(current, nearestMountedAncestor) { 25140 switch (current.tag) { 25141 case FunctionComponent: 25142 case ForwardRef: 25143 case SimpleMemoComponent: 25144 { 25145 if ( current.mode & ProfileMode) { 25146 startPassiveEffectTimer(); 25147 commitHookEffectListUnmount(Passive$1, current, nearestMountedAncestor); 25148 recordPassiveEffectDuration(current); 25149 } else { 25150 commitHookEffectListUnmount(Passive$1, current, nearestMountedAncestor); 25151 } 25152 25153 break; 25154 } 25155 } 25156 } // TODO: Reuse reappearLayoutEffects traversal here? 25157 25158 25159 function invokeLayoutEffectMountInDEV(fiber) { 25160 { 25161 // We don't need to re-check StrictEffectsMode here. 25162 // This function is only called if that check has already passed. 25163 switch (fiber.tag) { 25164 case FunctionComponent: 25165 case ForwardRef: 25166 case SimpleMemoComponent: 25167 { 25168 try { 25169 commitHookEffectListMount(Layout | HasEffect, fiber); 25170 } catch (error) { 25171 captureCommitPhaseError(fiber, fiber.return, error); 25172 } 25173 25174 break; 25175 } 25176 25177 case ClassComponent: 25178 { 25179 var instance = fiber.stateNode; 25180 25181 try { 25182 instance.componentDidMount(); 25183 } catch (error) { 25184 captureCommitPhaseError(fiber, fiber.return, error); 25185 } 25186 25187 break; 25188 } 25189 } 25190 } 25191 } 25192 25193 function invokePassiveEffectMountInDEV(fiber) { 25194 { 25195 // We don't need to re-check StrictEffectsMode here. 25196 // This function is only called if that check has already passed. 25197 switch (fiber.tag) { 25198 case FunctionComponent: 25199 case ForwardRef: 25200 case SimpleMemoComponent: 25201 { 25202 try { 25203 commitHookEffectListMount(Passive$1 | HasEffect, fiber); 25204 } catch (error) { 25205 captureCommitPhaseError(fiber, fiber.return, error); 25206 } 25207 25208 break; 25209 } 25210 } 25211 } 25212 } 25213 25214 function invokeLayoutEffectUnmountInDEV(fiber) { 25215 { 25216 // We don't need to re-check StrictEffectsMode here. 25217 // This function is only called if that check has already passed. 25218 switch (fiber.tag) { 25219 case FunctionComponent: 25220 case ForwardRef: 25221 case SimpleMemoComponent: 25222 { 25223 try { 25224 commitHookEffectListUnmount(Layout | HasEffect, fiber, fiber.return); 25225 } catch (error) { 25226 captureCommitPhaseError(fiber, fiber.return, error); 25227 } 25228 25229 break; 25230 } 25231 25232 case ClassComponent: 25233 { 25234 var instance = fiber.stateNode; 25235 25236 if (typeof instance.componentWillUnmount === 'function') { 25237 safelyCallComponentWillUnmount(fiber, fiber.return, instance); 25238 } 25239 25240 break; 25241 } 25242 } 25243 } 25244 } 25245 25246 function invokePassiveEffectUnmountInDEV(fiber) { 25247 { 25248 // We don't need to re-check StrictEffectsMode here. 25249 // This function is only called if that check has already passed. 25250 switch (fiber.tag) { 25251 case FunctionComponent: 25252 case ForwardRef: 25253 case SimpleMemoComponent: 25254 { 25255 try { 25256 commitHookEffectListUnmount(Passive$1 | HasEffect, fiber, fiber.return); 25257 } catch (error) { 25258 captureCommitPhaseError(fiber, fiber.return, error); 25259 } 25260 } 25261 } 25262 } 25263 } 25264 25265 var COMPONENT_TYPE = 0; 25266 var HAS_PSEUDO_CLASS_TYPE = 1; 25267 var ROLE_TYPE = 2; 25268 var TEST_NAME_TYPE = 3; 25269 var TEXT_TYPE = 4; 25270 25271 if (typeof Symbol === 'function' && Symbol.for) { 25272 var symbolFor = Symbol.for; 25273 COMPONENT_TYPE = symbolFor('selector.component'); 25274 HAS_PSEUDO_CLASS_TYPE = symbolFor('selector.has_pseudo_class'); 25275 ROLE_TYPE = symbolFor('selector.role'); 25276 TEST_NAME_TYPE = symbolFor('selector.test_id'); 25277 TEXT_TYPE = symbolFor('selector.text'); 25278 } 25279 var commitHooks = []; 25280 function onCommitRoot$1() { 25281 { 25282 commitHooks.forEach(function (commitHook) { 25283 return commitHook(); 25284 }); 25285 } 25286 } 25287 25288 var ReactCurrentActQueue = ReactSharedInternals.ReactCurrentActQueue; 25289 function isLegacyActEnvironment(fiber) { 25290 { 25291 // Legacy mode. We preserve the behavior of React 17's act. It assumes an 25292 // act environment whenever `jest` is defined, but you can still turn off 25293 // spurious warnings by setting IS_REACT_ACT_ENVIRONMENT explicitly 25294 // to false. 25295 var isReactActEnvironmentGlobal = // $FlowExpectedError – Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global 25296 typeof IS_REACT_ACT_ENVIRONMENT !== 'undefined' ? IS_REACT_ACT_ENVIRONMENT : undefined; // $FlowExpectedError - Flow doesn't know about jest 25297 25298 var jestIsDefined = typeof jest !== 'undefined'; 25299 return jestIsDefined && isReactActEnvironmentGlobal !== false; 25300 } 25301 } 25302 function isConcurrentActEnvironment() { 25303 { 25304 var isReactActEnvironmentGlobal = // $FlowExpectedError – Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global 25305 typeof IS_REACT_ACT_ENVIRONMENT !== 'undefined' ? IS_REACT_ACT_ENVIRONMENT : undefined; 25306 25307 if (!isReactActEnvironmentGlobal && ReactCurrentActQueue.current !== null) { 25308 // TODO: Include link to relevant documentation page. 25309 error('The current testing environment is not configured to support ' + 'act(...)'); 25310 } 25311 25312 return isReactActEnvironmentGlobal; 25313 } 25314 } 25315 25316 var ceil = Math.ceil; 25317 var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher, 25318 ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner, 25319 ReactCurrentBatchConfig$3 = ReactSharedInternals.ReactCurrentBatchConfig, 25320 ReactCurrentActQueue$1 = ReactSharedInternals.ReactCurrentActQueue; 25321 var NoContext = 25322 /* */ 25323 0; 25324 var BatchedContext = 25325 /* */ 25326 1; 25327 var RenderContext = 25328 /* */ 25329 2; 25330 var CommitContext = 25331 /* */ 25332 4; 25333 var RootInProgress = 0; 25334 var RootFatalErrored = 1; 25335 var RootErrored = 2; 25336 var RootSuspended = 3; 25337 var RootSuspendedWithDelay = 4; 25338 var RootCompleted = 5; 25339 var RootDidNotComplete = 6; // Describes where we are in the React execution stack 25340 25341 var executionContext = NoContext; // The root we're working on 25342 25343 var workInProgressRoot = null; // The fiber we're working on 25344 25345 var workInProgress = null; // The lanes we're rendering 25346 25347 var workInProgressRootRenderLanes = NoLanes; // Stack that allows components to change the render lanes for its subtree 25348 // This is a superset of the lanes we started working on at the root. The only 25349 // case where it's different from `workInProgressRootRenderLanes` is when we 25350 // enter a subtree that is hidden and needs to be unhidden: Suspense and 25351 // Offscreen component. 25352 // 25353 // Most things in the work loop should deal with workInProgressRootRenderLanes. 25354 // Most things in begin/complete phases should deal with subtreeRenderLanes. 25355 25356 var subtreeRenderLanes = NoLanes; 25357 var subtreeRenderLanesCursor = createCursor(NoLanes); // Whether to root completed, errored, suspended, etc. 25358 25359 var workInProgressRootExitStatus = RootInProgress; // A fatal error, if one is thrown 25360 25361 var workInProgressRootFatalError = null; // "Included" lanes refer to lanes that were worked on during this render. It's 25362 // slightly different than `renderLanes` because `renderLanes` can change as you 25363 // enter and exit an Offscreen tree. This value is the combination of all render 25364 // lanes for the entire render phase. 25365 25366 var workInProgressRootIncludedLanes = NoLanes; // The work left over by components that were visited during this render. Only 25367 // includes unprocessed updates, not work in bailed out children. 25368 25369 var workInProgressRootSkippedLanes = NoLanes; // Lanes that were updated (in an interleaved event) during this render. 25370 25371 var workInProgressRootInterleavedUpdatedLanes = NoLanes; // Lanes that were updated during the render phase (*not* an interleaved event). 25372 25373 var workInProgressRootPingedLanes = NoLanes; // Errors that are thrown during the render phase. 25374 25375 var workInProgressRootConcurrentErrors = null; // These are errors that we recovered from without surfacing them to the UI. 25376 // We will log them once the tree commits. 25377 25378 var workInProgressRootRecoverableErrors = null; // The most recent time we committed a fallback. This lets us ensure a train 25379 // model where we don't commit new loading states in too quick succession. 25380 25381 var globalMostRecentFallbackTime = 0; 25382 var FALLBACK_THROTTLE_MS = 500; // The absolute time for when we should start giving up on rendering 25383 // more and prefer CPU suspense heuristics instead. 25384 25385 var workInProgressRootRenderTargetTime = Infinity; // How long a render is supposed to take before we start following CPU 25386 // suspense heuristics and opt out of rendering more content. 25387 25388 var RENDER_TIMEOUT_MS = 500; 25389 var workInProgressTransitions = null; 25390 25391 function resetRenderTimer() { 25392 workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS; 25393 } 25394 25395 function getRenderTargetTime() { 25396 return workInProgressRootRenderTargetTime; 25397 } 25398 var hasUncaughtError = false; 25399 var firstUncaughtError = null; 25400 var legacyErrorBoundariesThatAlreadyFailed = null; // Only used when enableProfilerNestedUpdateScheduledHook is true; 25401 var rootDoesHavePassiveEffects = false; 25402 var rootWithPendingPassiveEffects = null; 25403 var pendingPassiveEffectsLanes = NoLanes; 25404 var pendingPassiveProfilerEffects = []; 25405 var pendingPassiveTransitions = null; // Use these to prevent an infinite loop of nested updates 25406 25407 var NESTED_UPDATE_LIMIT = 50; 25408 var nestedUpdateCount = 0; 25409 var rootWithNestedUpdates = null; 25410 var isFlushingPassiveEffects = false; 25411 var didScheduleUpdateDuringPassiveEffects = false; 25412 var NESTED_PASSIVE_UPDATE_LIMIT = 50; 25413 var nestedPassiveUpdateCount = 0; 25414 var rootWithPassiveNestedUpdates = null; // If two updates are scheduled within the same event, we should treat their 25415 // event times as simultaneous, even if the actual clock time has advanced 25416 // between the first and second call. 25417 25418 var currentEventTime = NoTimestamp; 25419 var currentEventTransitionLane = NoLanes; 25420 var isRunningInsertionEffect = false; 25421 function getWorkInProgressRoot() { 25422 return workInProgressRoot; 25423 } 25424 function requestEventTime() { 25425 if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { 25426 // We're inside React, so it's fine to read the actual time. 25427 return now(); 25428 } // We're not inside React, so we may be in the middle of a browser event. 25429 25430 25431 if (currentEventTime !== NoTimestamp) { 25432 // Use the same start time for all updates until we enter React again. 25433 return currentEventTime; 25434 } // This is the first update since React yielded. Compute a new start time. 25435 25436 25437 currentEventTime = now(); 25438 return currentEventTime; 25439 } 25440 function requestUpdateLane(fiber) { 25441 // Special cases 25442 var mode = fiber.mode; 25443 25444 if ((mode & ConcurrentMode) === NoMode) { 25445 return SyncLane; 25446 } else if ( (executionContext & RenderContext) !== NoContext && workInProgressRootRenderLanes !== NoLanes) { 25447 // This is a render phase update. These are not officially supported. The 25448 // old behavior is to give this the same "thread" (lanes) as 25449 // whatever is currently rendering. So if you call `setState` on a component 25450 // that happens later in the same render, it will flush. Ideally, we want to 25451 // remove the special case and treat them as if they came from an 25452 // interleaved event. Regardless, this pattern is not officially supported. 25453 // This behavior is only a fallback. The flag only exists until we can roll 25454 // out the setState warning, since existing code might accidentally rely on 25455 // the current behavior. 25456 return pickArbitraryLane(workInProgressRootRenderLanes); 25457 } 25458 25459 var isTransition = requestCurrentTransition() !== NoTransition; 25460 25461 if (isTransition) { 25462 if ( ReactCurrentBatchConfig$3.transition !== null) { 25463 var transition = ReactCurrentBatchConfig$3.transition; 25464 25465 if (!transition._updatedFibers) { 25466 transition._updatedFibers = new Set(); 25467 } 25468 25469 transition._updatedFibers.add(fiber); 25470 } // The algorithm for assigning an update to a lane should be stable for all 25471 // updates at the same priority within the same event. To do this, the 25472 // inputs to the algorithm must be the same. 25473 // 25474 // The trick we use is to cache the first of each of these inputs within an 25475 // event. Then reset the cached values once we can be sure the event is 25476 // over. Our heuristic for that is whenever we enter a concurrent work loop. 25477 25478 25479 if (currentEventTransitionLane === NoLane) { 25480 // All transitions within the same event are assigned the same lane. 25481 currentEventTransitionLane = claimNextTransitionLane(); 25482 } 25483 25484 return currentEventTransitionLane; 25485 } // Updates originating inside certain React methods, like flushSync, have 25486 // their priority set by tracking it with a context variable. 25487 // 25488 // The opaque type returned by the host config is internally a lane, so we can 25489 // use that directly. 25490 // TODO: Move this type conversion to the event priority module. 25491 25492 25493 var updateLane = getCurrentUpdatePriority(); 25494 25495 if (updateLane !== NoLane) { 25496 return updateLane; 25497 } // This update originated outside React. Ask the host environment for an 25498 // appropriate priority, based on the type of event. 25499 // 25500 // The opaque type returned by the host config is internally a lane, so we can 25501 // use that directly. 25502 // TODO: Move this type conversion to the event priority module. 25503 25504 25505 var eventLane = getCurrentEventPriority(); 25506 return eventLane; 25507 } 25508 25509 function requestRetryLane(fiber) { 25510 // This is a fork of `requestUpdateLane` designed specifically for Suspense 25511 // "retries" — a special update that attempts to flip a Suspense boundary 25512 // from its placeholder state to its primary/resolved state. 25513 // Special cases 25514 var mode = fiber.mode; 25515 25516 if ((mode & ConcurrentMode) === NoMode) { 25517 return SyncLane; 25518 } 25519 25520 return claimNextRetryLane(); 25521 } 25522 25523 function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { 25524 checkForNestedUpdates(); 25525 25526 { 25527 if (isRunningInsertionEffect) { 25528 error('useInsertionEffect must not schedule updates.'); 25529 } 25530 } 25531 25532 { 25533 if (isFlushingPassiveEffects) { 25534 didScheduleUpdateDuringPassiveEffects = true; 25535 } 25536 } // Mark that the root has a pending update. 25537 25538 25539 markRootUpdated(root, lane, eventTime); 25540 25541 if ((executionContext & RenderContext) !== NoLanes && root === workInProgressRoot) { 25542 // This update was dispatched during the render phase. This is a mistake 25543 // if the update originates from user space (with the exception of local 25544 // hook updates, which are handled differently and don't reach this 25545 // function), but there are some internal React features that use this as 25546 // an implementation detail, like selective hydration. 25547 warnAboutRenderPhaseUpdatesInDEV(fiber); // Track lanes that were updated during the render phase 25548 } else { 25549 // This is a normal update, scheduled from outside the render phase. For 25550 // example, during an input event. 25551 { 25552 if (isDevToolsPresent) { 25553 addFiberToLanesMap(root, fiber, lane); 25554 } 25555 } 25556 25557 warnIfUpdatesNotWrappedWithActDEV(fiber); 25558 25559 if (root === workInProgressRoot) { 25560 // Received an update to a tree that's in the middle of rendering. Mark 25561 // that there was an interleaved update work on this root. Unless the 25562 // `deferRenderPhaseUpdateToNextBatch` flag is off and this is a render 25563 // phase update. In that case, we don't treat render phase updates as if 25564 // they were interleaved, for backwards compat reasons. 25565 if ( (executionContext & RenderContext) === NoContext) { 25566 workInProgressRootInterleavedUpdatedLanes = mergeLanes(workInProgressRootInterleavedUpdatedLanes, lane); 25567 } 25568 25569 if (workInProgressRootExitStatus === RootSuspendedWithDelay) { 25570 // The root already suspended with a delay, which means this render 25571 // definitely won't finish. Since we have a new update, let's mark it as 25572 // suspended now, right before marking the incoming update. This has the 25573 // effect of interrupting the current render and switching to the update. 25574 // TODO: Make sure this doesn't override pings that happen while we've 25575 // already started rendering. 25576 markRootSuspended$1(root, workInProgressRootRenderLanes); 25577 } 25578 } 25579 25580 ensureRootIsScheduled(root, eventTime); 25581 25582 if (lane === SyncLane && executionContext === NoContext && (fiber.mode & ConcurrentMode) === NoMode && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. 25583 !( ReactCurrentActQueue$1.isBatchingLegacy)) { 25584 // Flush the synchronous work now, unless we're already working or inside 25585 // a batch. This is intentionally inside scheduleUpdateOnFiber instead of 25586 // scheduleCallbackForFiber to preserve the ability to schedule a callback 25587 // without immediately flushing it. We only do this for user-initiated 25588 // updates, to preserve historical behavior of legacy mode. 25589 resetRenderTimer(); 25590 flushSyncCallbacksOnlyInLegacyMode(); 25591 } 25592 } 25593 } 25594 function scheduleInitialHydrationOnRoot(root, lane, eventTime) { 25595 // This is a special fork of scheduleUpdateOnFiber that is only used to 25596 // schedule the initial hydration of a root that has just been created. Most 25597 // of the stuff in scheduleUpdateOnFiber can be skipped. 25598 // 25599 // The main reason for this separate path, though, is to distinguish the 25600 // initial children from subsequent updates. In fully client-rendered roots 25601 // (createRoot instead of hydrateRoot), all top-level renders are modeled as 25602 // updates, but hydration roots are special because the initial render must 25603 // match what was rendered on the server. 25604 var current = root.current; 25605 current.lanes = lane; 25606 markRootUpdated(root, lane, eventTime); 25607 ensureRootIsScheduled(root, eventTime); 25608 } 25609 function isUnsafeClassRenderPhaseUpdate(fiber) { 25610 // Check if this is a render phase update. Only called by class components, 25611 // which special (deprecated) behavior for UNSAFE_componentWillReceive props. 25612 return (// TODO: Remove outdated deferRenderPhaseUpdateToNextBatch experiment. We 25613 // decided not to enable it. 25614 (executionContext & RenderContext) !== NoContext 25615 ); 25616 } // Use this function to schedule a task for a root. There's only one task per 25617 // root; if a task was already scheduled, we'll check to make sure the priority 25618 // of the existing task is the same as the priority of the next level that the 25619 // root has work on. This function is called on every update, and right before 25620 // exiting a task. 25621 25622 function ensureRootIsScheduled(root, currentTime) { 25623 var existingCallbackNode = root.callbackNode; // Check if any lanes are being starved by other work. If so, mark them as 25624 // expired so we know to work on those next. 25625 25626 markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. 25627 25628 var nextLanes = getNextLanes(root, root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes); 25629 25630 if (nextLanes === NoLanes) { 25631 // Special case: There's nothing to work on. 25632 if (existingCallbackNode !== null) { 25633 cancelCallback$1(existingCallbackNode); 25634 } 25635 25636 root.callbackNode = null; 25637 root.callbackPriority = NoLane; 25638 return; 25639 } // We use the highest priority lane to represent the priority of the callback. 25640 25641 25642 var newCallbackPriority = getHighestPriorityLane(nextLanes); // Check if there's an existing task. We may be able to reuse it. 25643 25644 var existingCallbackPriority = root.callbackPriority; 25645 25646 if (existingCallbackPriority === newCallbackPriority && // Special case related to `act`. If the currently scheduled task is a 25647 // Scheduler task, rather than an `act` task, cancel it and re-scheduled 25648 // on the `act` queue. 25649 !( ReactCurrentActQueue$1.current !== null && existingCallbackNode !== fakeActCallbackNode)) { 25650 { 25651 // If we're going to re-use an existing task, it needs to exist. 25652 // Assume that discrete update microtasks are non-cancellable and null. 25653 // TODO: Temporary until we confirm this warning is not fired. 25654 if (existingCallbackNode == null && existingCallbackPriority !== SyncLane) { 25655 error('Expected scheduled callback to exist. This error is likely caused by a bug in React. Please file an issue.'); 25656 } 25657 } // The priority hasn't changed. We can reuse the existing task. Exit. 25658 25659 25660 return; 25661 } 25662 25663 if (existingCallbackNode != null) { 25664 // Cancel the existing callback. We'll schedule a new one below. 25665 cancelCallback$1(existingCallbackNode); 25666 } // Schedule a new callback. 25667 25668 25669 var newCallbackNode; 25670 25671 if (newCallbackPriority === SyncLane) { 25672 // Special case: Sync React callbacks are scheduled on a special 25673 // internal queue 25674 if (root.tag === LegacyRoot) { 25675 if ( ReactCurrentActQueue$1.isBatchingLegacy !== null) { 25676 ReactCurrentActQueue$1.didScheduleLegacyUpdate = true; 25677 } 25678 25679 scheduleLegacySyncCallback(performSyncWorkOnRoot.bind(null, root)); 25680 } else { 25681 scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)); 25682 } 25683 25684 { 25685 // Flush the queue in a microtask. 25686 if ( ReactCurrentActQueue$1.current !== null) { 25687 // Inside `act`, use our internal `act` queue so that these get flushed 25688 // at the end of the current scope even when using the sync version 25689 // of `act`. 25690 ReactCurrentActQueue$1.current.push(flushSyncCallbacks); 25691 } else { 25692 scheduleMicrotask(function () { 25693 // In Safari, appending an iframe forces microtasks to run. 25694 // https://github.com/facebook/react/issues/22459 25695 // We don't support running callbacks in the middle of render 25696 // or commit so we need to check against that. 25697 if ((executionContext & (RenderContext | CommitContext)) === NoContext) { 25698 // Note that this would still prematurely flush the callbacks 25699 // if this happens outside render or commit phase (e.g. in an event). 25700 flushSyncCallbacks(); 25701 } 25702 }); 25703 } 25704 } 25705 25706 newCallbackNode = null; 25707 } else { 25708 var schedulerPriorityLevel; 25709 25710 switch (lanesToEventPriority(nextLanes)) { 25711 case DiscreteEventPriority: 25712 schedulerPriorityLevel = ImmediatePriority; 25713 break; 25714 25715 case ContinuousEventPriority: 25716 schedulerPriorityLevel = UserBlockingPriority; 25717 break; 25718 25719 case DefaultEventPriority: 25720 schedulerPriorityLevel = NormalPriority; 25721 break; 25722 25723 case IdleEventPriority: 25724 schedulerPriorityLevel = IdlePriority; 25725 break; 25726 25727 default: 25728 schedulerPriorityLevel = NormalPriority; 25729 break; 25730 } 25731 25732 newCallbackNode = scheduleCallback$1(schedulerPriorityLevel, performConcurrentWorkOnRoot.bind(null, root)); 25733 } 25734 25735 root.callbackPriority = newCallbackPriority; 25736 root.callbackNode = newCallbackNode; 25737 } // This is the entry point for every concurrent task, i.e. anything that 25738 // goes through Scheduler. 25739 25740 25741 function performConcurrentWorkOnRoot(root, didTimeout) { 25742 { 25743 resetNestedUpdateFlag(); 25744 } // Since we know we're in a React event, we can clear the current 25745 // event time. The next update will compute a new event time. 25746 25747 25748 currentEventTime = NoTimestamp; 25749 currentEventTransitionLane = NoLanes; 25750 25751 if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { 25752 throw new Error('Should not already be working.'); 25753 } // Flush any pending passive effects before deciding which lanes to work on, 25754 // in case they schedule additional work. 25755 25756 25757 var originalCallbackNode = root.callbackNode; 25758 var didFlushPassiveEffects = flushPassiveEffects(); 25759 25760 if (didFlushPassiveEffects) { 25761 // Something in the passive effect phase may have canceled the current task. 25762 // Check if the task node for this root was changed. 25763 if (root.callbackNode !== originalCallbackNode) { 25764 // The current task was canceled. Exit. We don't need to call 25765 // `ensureRootIsScheduled` because the check above implies either that 25766 // there's a new task, or that there's no remaining work on this root. 25767 return null; 25768 } 25769 } // Determine the next lanes to work on, using the fields stored 25770 // on the root. 25771 25772 25773 var lanes = getNextLanes(root, root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes); 25774 25775 if (lanes === NoLanes) { 25776 // Defensive coding. This is never expected to happen. 25777 return null; 25778 } // We disable time-slicing in some cases: if the work has been CPU-bound 25779 // for too long ("expired" work, to prevent starvation), or we're in 25780 // sync-updates-by-default mode. 25781 // TODO: We only check `didTimeout` defensively, to account for a Scheduler 25782 // bug we're still investigating. Once the bug in Scheduler is fixed, 25783 // we can remove this, since we track expiration ourselves. 25784 25785 25786 var shouldTimeSlice = !includesBlockingLane(root, lanes) && !includesExpiredLane(root, lanes) && ( !didTimeout); 25787 var exitStatus = shouldTimeSlice ? renderRootConcurrent(root, lanes) : renderRootSync(root, lanes); 25788 25789 if (exitStatus !== RootInProgress) { 25790 if (exitStatus === RootErrored) { 25791 // If something threw an error, try rendering one more time. We'll 25792 // render synchronously to block concurrent data mutations, and we'll 25793 // includes all pending updates are included. If it still fails after 25794 // the second attempt, we'll give up and commit the resulting tree. 25795 var errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); 25796 25797 if (errorRetryLanes !== NoLanes) { 25798 lanes = errorRetryLanes; 25799 exitStatus = recoverFromConcurrentError(root, errorRetryLanes); 25800 } 25801 } 25802 25803 if (exitStatus === RootFatalErrored) { 25804 var fatalError = workInProgressRootFatalError; 25805 prepareFreshStack(root, NoLanes); 25806 markRootSuspended$1(root, lanes); 25807 ensureRootIsScheduled(root, now()); 25808 throw fatalError; 25809 } 25810 25811 if (exitStatus === RootDidNotComplete) { 25812 // The render unwound without completing the tree. This happens in special 25813 // cases where need to exit the current render without producing a 25814 // consistent tree or committing. 25815 // 25816 // This should only happen during a concurrent render, not a discrete or 25817 // synchronous update. We should have already checked for this when we 25818 // unwound the stack. 25819 markRootSuspended$1(root, lanes); 25820 } else { 25821 // The render completed. 25822 // Check if this render may have yielded to a concurrent event, and if so, 25823 // confirm that any newly rendered stores are consistent. 25824 // TODO: It's possible that even a concurrent render may never have yielded 25825 // to the main thread, if it was fast enough, or if it expired. We could 25826 // skip the consistency check in that case, too. 25827 var renderWasConcurrent = !includesBlockingLane(root, lanes); 25828 var finishedWork = root.current.alternate; 25829 25830 if (renderWasConcurrent && !isRenderConsistentWithExternalStores(finishedWork)) { 25831 // A store was mutated in an interleaved event. Render again, 25832 // synchronously, to block further mutations. 25833 exitStatus = renderRootSync(root, lanes); // We need to check again if something threw 25834 25835 if (exitStatus === RootErrored) { 25836 var _errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); 25837 25838 if (_errorRetryLanes !== NoLanes) { 25839 lanes = _errorRetryLanes; 25840 exitStatus = recoverFromConcurrentError(root, _errorRetryLanes); // We assume the tree is now consistent because we didn't yield to any 25841 // concurrent events. 25842 } 25843 } 25844 25845 if (exitStatus === RootFatalErrored) { 25846 var _fatalError = workInProgressRootFatalError; 25847 prepareFreshStack(root, NoLanes); 25848 markRootSuspended$1(root, lanes); 25849 ensureRootIsScheduled(root, now()); 25850 throw _fatalError; 25851 } 25852 } // We now have a consistent tree. The next step is either to commit it, 25853 // or, if something suspended, wait to commit it after a timeout. 25854 25855 25856 root.finishedWork = finishedWork; 25857 root.finishedLanes = lanes; 25858 finishConcurrentRender(root, exitStatus, lanes); 25859 } 25860 } 25861 25862 ensureRootIsScheduled(root, now()); 25863 25864 if (root.callbackNode === originalCallbackNode) { 25865 // The task node scheduled for this root is the same one that's 25866 // currently executed. Need to return a continuation. 25867 return performConcurrentWorkOnRoot.bind(null, root); 25868 } 25869 25870 return null; 25871 } 25872 25873 function recoverFromConcurrentError(root, errorRetryLanes) { 25874 // If an error occurred during hydration, discard server response and fall 25875 // back to client side render. 25876 // Before rendering again, save the errors from the previous attempt. 25877 var errorsFromFirstAttempt = workInProgressRootConcurrentErrors; 25878 25879 if (isRootDehydrated(root)) { 25880 // The shell failed to hydrate. Set a flag to force a client rendering 25881 // during the next attempt. To do this, we call prepareFreshStack now 25882 // to create the root work-in-progress fiber. This is a bit weird in terms 25883 // of factoring, because it relies on renderRootSync not calling 25884 // prepareFreshStack again in the call below, which happens because the 25885 // root and lanes haven't changed. 25886 // 25887 // TODO: I think what we should do is set ForceClientRender inside 25888 // throwException, like we do for nested Suspense boundaries. The reason 25889 // it's here instead is so we can switch to the synchronous work loop, too. 25890 // Something to consider for a future refactor. 25891 var rootWorkInProgress = prepareFreshStack(root, errorRetryLanes); 25892 rootWorkInProgress.flags |= ForceClientRender; 25893 25894 { 25895 errorHydratingContainer(root.containerInfo); 25896 } 25897 } 25898 25899 var exitStatus = renderRootSync(root, errorRetryLanes); 25900 25901 if (exitStatus !== RootErrored) { 25902 // Successfully finished rendering on retry 25903 // The errors from the failed first attempt have been recovered. Add 25904 // them to the collection of recoverable errors. We'll log them in the 25905 // commit phase. 25906 var errorsFromSecondAttempt = workInProgressRootRecoverableErrors; 25907 workInProgressRootRecoverableErrors = errorsFromFirstAttempt; // The errors from the second attempt should be queued after the errors 25908 // from the first attempt, to preserve the causal sequence. 25909 25910 if (errorsFromSecondAttempt !== null) { 25911 queueRecoverableErrors(errorsFromSecondAttempt); 25912 } 25913 } 25914 25915 return exitStatus; 25916 } 25917 25918 function queueRecoverableErrors(errors) { 25919 if (workInProgressRootRecoverableErrors === null) { 25920 workInProgressRootRecoverableErrors = errors; 25921 } else { 25922 workInProgressRootRecoverableErrors.push.apply(workInProgressRootRecoverableErrors, errors); 25923 } 25924 } 25925 25926 function finishConcurrentRender(root, exitStatus, lanes) { 25927 switch (exitStatus) { 25928 case RootInProgress: 25929 case RootFatalErrored: 25930 { 25931 throw new Error('Root did not complete. This is a bug in React.'); 25932 } 25933 // Flow knows about invariant, so it complains if I add a break 25934 // statement, but eslint doesn't know about invariant, so it complains 25935 // if I do. eslint-disable-next-line no-fallthrough 25936 25937 case RootErrored: 25938 { 25939 // We should have already attempted to retry this tree. If we reached 25940 // this point, it errored again. Commit it. 25941 commitRoot(root, workInProgressRootRecoverableErrors, workInProgressTransitions); 25942 break; 25943 } 25944 25945 case RootSuspended: 25946 { 25947 markRootSuspended$1(root, lanes); // We have an acceptable loading state. We need to figure out if we 25948 // should immediately commit it or wait a bit. 25949 25950 if (includesOnlyRetries(lanes) && // do not delay if we're inside an act() scope 25951 !shouldForceFlushFallbacksInDEV()) { 25952 // This render only included retries, no updates. Throttle committing 25953 // retries so that we don't show too many loading states too quickly. 25954 var msUntilTimeout = globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now(); // Don't bother with a very short suspense time. 25955 25956 if (msUntilTimeout > 10) { 25957 var nextLanes = getNextLanes(root, NoLanes); 25958 25959 if (nextLanes !== NoLanes) { 25960 // There's additional work on this root. 25961 break; 25962 } 25963 25964 var suspendedLanes = root.suspendedLanes; 25965 25966 if (!isSubsetOfLanes(suspendedLanes, lanes)) { 25967 // We should prefer to render the fallback of at the last 25968 // suspended level. Ping the last suspended level to try 25969 // rendering it again. 25970 // FIXME: What if the suspended lanes are Idle? Should not restart. 25971 var eventTime = requestEventTime(); 25972 markRootPinged(root, suspendedLanes); 25973 break; 25974 } // The render is suspended, it hasn't timed out, and there's no 25975 // lower priority work to do. Instead of committing the fallback 25976 // immediately, wait for more data to arrive. 25977 25978 25979 root.timeoutHandle = scheduleTimeout(commitRoot.bind(null, root, workInProgressRootRecoverableErrors, workInProgressTransitions), msUntilTimeout); 25980 break; 25981 } 25982 } // The work expired. Commit immediately. 25983 25984 25985 commitRoot(root, workInProgressRootRecoverableErrors, workInProgressTransitions); 25986 break; 25987 } 25988 25989 case RootSuspendedWithDelay: 25990 { 25991 markRootSuspended$1(root, lanes); 25992 25993 if (includesOnlyTransitions(lanes)) { 25994 // This is a transition, so we should exit without committing a 25995 // placeholder and without scheduling a timeout. Delay indefinitely 25996 // until we receive more data. 25997 break; 25998 } 25999 26000 if (!shouldForceFlushFallbacksInDEV()) { 26001 // This is not a transition, but we did trigger an avoided state. 26002 // Schedule a placeholder to display after a short delay, using the Just 26003 // Noticeable Difference. 26004 // TODO: Is the JND optimization worth the added complexity? If this is 26005 // the only reason we track the event time, then probably not. 26006 // Consider removing. 26007 var mostRecentEventTime = getMostRecentEventTime(root, lanes); 26008 var eventTimeMs = mostRecentEventTime; 26009 var timeElapsedMs = now() - eventTimeMs; 26010 26011 var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time. 26012 26013 26014 if (_msUntilTimeout > 10) { 26015 // Instead of committing the fallback immediately, wait for more data 26016 // to arrive. 26017 root.timeoutHandle = scheduleTimeout(commitRoot.bind(null, root, workInProgressRootRecoverableErrors, workInProgressTransitions), _msUntilTimeout); 26018 break; 26019 } 26020 } // Commit the placeholder. 26021 26022 26023 commitRoot(root, workInProgressRootRecoverableErrors, workInProgressTransitions); 26024 break; 26025 } 26026 26027 case RootCompleted: 26028 { 26029 // The work completed. Ready to commit. 26030 commitRoot(root, workInProgressRootRecoverableErrors, workInProgressTransitions); 26031 break; 26032 } 26033 26034 default: 26035 { 26036 throw new Error('Unknown root exit status.'); 26037 } 26038 } 26039 } 26040 26041 function isRenderConsistentWithExternalStores(finishedWork) { 26042 // Search the rendered tree for external store reads, and check whether the 26043 // stores were mutated in a concurrent event. Intentionally using an iterative 26044 // loop instead of recursion so we can exit early. 26045 var node = finishedWork; 26046 26047 while (true) { 26048 if (node.flags & StoreConsistency) { 26049 var updateQueue = node.updateQueue; 26050 26051 if (updateQueue !== null) { 26052 var checks = updateQueue.stores; 26053 26054 if (checks !== null) { 26055 for (var i = 0; i < checks.length; i++) { 26056 var check = checks[i]; 26057 var getSnapshot = check.getSnapshot; 26058 var renderedValue = check.value; 26059 26060 try { 26061 if (!objectIs(getSnapshot(), renderedValue)) { 26062 // Found an inconsistent store. 26063 return false; 26064 } 26065 } catch (error) { 26066 // If `getSnapshot` throws, return `false`. This will schedule 26067 // a re-render, and the error will be rethrown during render. 26068 return false; 26069 } 26070 } 26071 } 26072 } 26073 } 26074 26075 var child = node.child; 26076 26077 if (node.subtreeFlags & StoreConsistency && child !== null) { 26078 child.return = node; 26079 node = child; 26080 continue; 26081 } 26082 26083 if (node === finishedWork) { 26084 return true; 26085 } 26086 26087 while (node.sibling === null) { 26088 if (node.return === null || node.return === finishedWork) { 26089 return true; 26090 } 26091 26092 node = node.return; 26093 } 26094 26095 node.sibling.return = node.return; 26096 node = node.sibling; 26097 } // Flow doesn't know this is unreachable, but eslint does 26098 // eslint-disable-next-line no-unreachable 26099 26100 26101 return true; 26102 } 26103 26104 function markRootSuspended$1(root, suspendedLanes) { 26105 // When suspending, we should always exclude lanes that were pinged or (more 26106 // rarely, since we try to avoid it) updated during the render phase. 26107 // TODO: Lol maybe there's a better way to factor this besides this 26108 // obnoxiously named function :) 26109 suspendedLanes = removeLanes(suspendedLanes, workInProgressRootPingedLanes); 26110 suspendedLanes = removeLanes(suspendedLanes, workInProgressRootInterleavedUpdatedLanes); 26111 markRootSuspended(root, suspendedLanes); 26112 } // This is the entry point for synchronous tasks that don't go 26113 // through Scheduler 26114 26115 26116 function performSyncWorkOnRoot(root) { 26117 { 26118 syncNestedUpdateFlag(); 26119 } 26120 26121 if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { 26122 throw new Error('Should not already be working.'); 26123 } 26124 26125 flushPassiveEffects(); 26126 var lanes = getNextLanes(root, NoLanes); 26127 26128 if (!includesSomeLane(lanes, SyncLane)) { 26129 // There's no remaining sync work left. 26130 ensureRootIsScheduled(root, now()); 26131 return null; 26132 } 26133 26134 var exitStatus = renderRootSync(root, lanes); 26135 26136 if (root.tag !== LegacyRoot && exitStatus === RootErrored) { 26137 // If something threw an error, try rendering one more time. We'll render 26138 // synchronously to block concurrent data mutations, and we'll includes 26139 // all pending updates are included. If it still fails after the second 26140 // attempt, we'll give up and commit the resulting tree. 26141 var errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); 26142 26143 if (errorRetryLanes !== NoLanes) { 26144 lanes = errorRetryLanes; 26145 exitStatus = recoverFromConcurrentError(root, errorRetryLanes); 26146 } 26147 } 26148 26149 if (exitStatus === RootFatalErrored) { 26150 var fatalError = workInProgressRootFatalError; 26151 prepareFreshStack(root, NoLanes); 26152 markRootSuspended$1(root, lanes); 26153 ensureRootIsScheduled(root, now()); 26154 throw fatalError; 26155 } 26156 26157 if (exitStatus === RootDidNotComplete) { 26158 throw new Error('Root did not complete. This is a bug in React.'); 26159 } // We now have a consistent tree. Because this is a sync render, we 26160 // will commit it even if something suspended. 26161 26162 26163 var finishedWork = root.current.alternate; 26164 root.finishedWork = finishedWork; 26165 root.finishedLanes = lanes; 26166 commitRoot(root, workInProgressRootRecoverableErrors, workInProgressTransitions); // Before exiting, make sure there's a callback scheduled for the next 26167 // pending level. 26168 26169 ensureRootIsScheduled(root, now()); 26170 return null; 26171 } 26172 26173 function flushRoot(root, lanes) { 26174 if (lanes !== NoLanes) { 26175 markRootEntangled(root, mergeLanes(lanes, SyncLane)); 26176 ensureRootIsScheduled(root, now()); 26177 26178 if ((executionContext & (RenderContext | CommitContext)) === NoContext) { 26179 resetRenderTimer(); 26180 flushSyncCallbacks(); 26181 } 26182 } 26183 } 26184 function batchedUpdates$1(fn, a) { 26185 var prevExecutionContext = executionContext; 26186 executionContext |= BatchedContext; 26187 26188 try { 26189 return fn(a); 26190 } finally { 26191 executionContext = prevExecutionContext; // If there were legacy sync updates, flush them at the end of the outer 26192 // most batchedUpdates-like method. 26193 26194 if (executionContext === NoContext && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. 26195 !( ReactCurrentActQueue$1.isBatchingLegacy)) { 26196 resetRenderTimer(); 26197 flushSyncCallbacksOnlyInLegacyMode(); 26198 } 26199 } 26200 } 26201 function discreteUpdates(fn, a, b, c, d) { 26202 var previousPriority = getCurrentUpdatePriority(); 26203 var prevTransition = ReactCurrentBatchConfig$3.transition; 26204 26205 try { 26206 ReactCurrentBatchConfig$3.transition = null; 26207 setCurrentUpdatePriority(DiscreteEventPriority); 26208 return fn(a, b, c, d); 26209 } finally { 26210 setCurrentUpdatePriority(previousPriority); 26211 ReactCurrentBatchConfig$3.transition = prevTransition; 26212 26213 if (executionContext === NoContext) { 26214 resetRenderTimer(); 26215 } 26216 } 26217 } // Overload the definition to the two valid signatures. 26218 // Warning, this opts-out of checking the function body. 26219 26220 // eslint-disable-next-line no-redeclare 26221 function flushSync(fn) { 26222 // In legacy mode, we flush pending passive effects at the beginning of the 26223 // next event, not at the end of the previous one. 26224 if (rootWithPendingPassiveEffects !== null && rootWithPendingPassiveEffects.tag === LegacyRoot && (executionContext & (RenderContext | CommitContext)) === NoContext) { 26225 flushPassiveEffects(); 26226 } 26227 26228 var prevExecutionContext = executionContext; 26229 executionContext |= BatchedContext; 26230 var prevTransition = ReactCurrentBatchConfig$3.transition; 26231 var previousPriority = getCurrentUpdatePriority(); 26232 26233 try { 26234 ReactCurrentBatchConfig$3.transition = null; 26235 setCurrentUpdatePriority(DiscreteEventPriority); 26236 26237 if (fn) { 26238 return fn(); 26239 } else { 26240 return undefined; 26241 } 26242 } finally { 26243 setCurrentUpdatePriority(previousPriority); 26244 ReactCurrentBatchConfig$3.transition = prevTransition; 26245 executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. 26246 // Note that this will happen even if batchedUpdates is higher up 26247 // the stack. 26248 26249 if ((executionContext & (RenderContext | CommitContext)) === NoContext) { 26250 flushSyncCallbacks(); 26251 } 26252 } 26253 } 26254 function isAlreadyRendering() { 26255 // Used by the renderer to print a warning if certain APIs are called from 26256 // the wrong context. 26257 return (executionContext & (RenderContext | CommitContext)) !== NoContext; 26258 } 26259 function pushRenderLanes(fiber, lanes) { 26260 push(subtreeRenderLanesCursor, subtreeRenderLanes, fiber); 26261 subtreeRenderLanes = mergeLanes(subtreeRenderLanes, lanes); 26262 workInProgressRootIncludedLanes = mergeLanes(workInProgressRootIncludedLanes, lanes); 26263 } 26264 function popRenderLanes(fiber) { 26265 subtreeRenderLanes = subtreeRenderLanesCursor.current; 26266 pop(subtreeRenderLanesCursor, fiber); 26267 } 26268 26269 function prepareFreshStack(root, lanes) { 26270 root.finishedWork = null; 26271 root.finishedLanes = NoLanes; 26272 var timeoutHandle = root.timeoutHandle; 26273 26274 if (timeoutHandle !== noTimeout) { 26275 // The root previous suspended and scheduled a timeout to commit a fallback 26276 // state. Now that we have additional work, cancel the timeout. 26277 root.timeoutHandle = noTimeout; // $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above 26278 26279 cancelTimeout(timeoutHandle); 26280 } 26281 26282 if (workInProgress !== null) { 26283 var interruptedWork = workInProgress.return; 26284 26285 while (interruptedWork !== null) { 26286 var current = interruptedWork.alternate; 26287 unwindInterruptedWork(current, interruptedWork); 26288 interruptedWork = interruptedWork.return; 26289 } 26290 } 26291 26292 workInProgressRoot = root; 26293 var rootWorkInProgress = createWorkInProgress(root.current, null); 26294 workInProgress = rootWorkInProgress; 26295 workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; 26296 workInProgressRootExitStatus = RootInProgress; 26297 workInProgressRootFatalError = null; 26298 workInProgressRootSkippedLanes = NoLanes; 26299 workInProgressRootInterleavedUpdatedLanes = NoLanes; 26300 workInProgressRootPingedLanes = NoLanes; 26301 workInProgressRootConcurrentErrors = null; 26302 workInProgressRootRecoverableErrors = null; 26303 finishQueueingConcurrentUpdates(); 26304 26305 { 26306 ReactStrictModeWarnings.discardPendingWarnings(); 26307 } 26308 26309 return rootWorkInProgress; 26310 } 26311 26312 function handleError(root, thrownValue) { 26313 do { 26314 var erroredWork = workInProgress; 26315 26316 try { 26317 // Reset module-level state that was set during the render phase. 26318 resetContextDependencies(); 26319 resetHooksAfterThrow(); 26320 resetCurrentFiber(); // TODO: I found and added this missing line while investigating a 26321 // separate issue. Write a regression test using string refs. 26322 26323 ReactCurrentOwner$2.current = null; 26324 26325 if (erroredWork === null || erroredWork.return === null) { 26326 // Expected to be working on a non-root fiber. This is a fatal error 26327 // because there's no ancestor that can handle it; the root is 26328 // supposed to capture all errors that weren't caught by an error 26329 // boundary. 26330 workInProgressRootExitStatus = RootFatalErrored; 26331 workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next 26332 // sibling, or the parent if there are no siblings. But since the root 26333 // has no siblings nor a parent, we set it to null. Usually this is 26334 // handled by `completeUnitOfWork` or `unwindWork`, but since we're 26335 // intentionally not calling those, we need set it here. 26336 // TODO: Consider calling `unwindWork` to pop the contexts. 26337 26338 workInProgress = null; 26339 return; 26340 } 26341 26342 if (enableProfilerTimer && erroredWork.mode & ProfileMode) { 26343 // Record the time spent rendering before an error was thrown. This 26344 // avoids inaccurate Profiler durations in the case of a 26345 // suspended render. 26346 stopProfilerTimerIfRunningAndRecordDelta(erroredWork, true); 26347 } 26348 26349 if (enableSchedulingProfiler) { 26350 markComponentRenderStopped(); 26351 26352 if (thrownValue !== null && typeof thrownValue === 'object' && typeof thrownValue.then === 'function') { 26353 var wakeable = thrownValue; 26354 markComponentSuspended(erroredWork, wakeable, workInProgressRootRenderLanes); 26355 } else { 26356 markComponentErrored(erroredWork, thrownValue, workInProgressRootRenderLanes); 26357 } 26358 } 26359 26360 throwException(root, erroredWork.return, erroredWork, thrownValue, workInProgressRootRenderLanes); 26361 completeUnitOfWork(erroredWork); 26362 } catch (yetAnotherThrownValue) { 26363 // Something in the return path also threw. 26364 thrownValue = yetAnotherThrownValue; 26365 26366 if (workInProgress === erroredWork && erroredWork !== null) { 26367 // If this boundary has already errored, then we had trouble processing 26368 // the error. Bubble it to the next boundary. 26369 erroredWork = erroredWork.return; 26370 workInProgress = erroredWork; 26371 } else { 26372 erroredWork = workInProgress; 26373 } 26374 26375 continue; 26376 } // Return to the normal work loop. 26377 26378 26379 return; 26380 } while (true); 26381 } 26382 26383 function pushDispatcher() { 26384 var prevDispatcher = ReactCurrentDispatcher$2.current; 26385 ReactCurrentDispatcher$2.current = ContextOnlyDispatcher; 26386 26387 if (prevDispatcher === null) { 26388 // The React isomorphic package does not include a default dispatcher. 26389 // Instead the first renderer will lazily attach one, in order to give 26390 // nicer error messages. 26391 return ContextOnlyDispatcher; 26392 } else { 26393 return prevDispatcher; 26394 } 26395 } 26396 26397 function popDispatcher(prevDispatcher) { 26398 ReactCurrentDispatcher$2.current = prevDispatcher; 26399 } 26400 26401 function markCommitTimeOfFallback() { 26402 globalMostRecentFallbackTime = now(); 26403 } 26404 function markSkippedUpdateLanes(lane) { 26405 workInProgressRootSkippedLanes = mergeLanes(lane, workInProgressRootSkippedLanes); 26406 } 26407 function renderDidSuspend() { 26408 if (workInProgressRootExitStatus === RootInProgress) { 26409 workInProgressRootExitStatus = RootSuspended; 26410 } 26411 } 26412 function renderDidSuspendDelayIfPossible() { 26413 if (workInProgressRootExitStatus === RootInProgress || workInProgressRootExitStatus === RootSuspended || workInProgressRootExitStatus === RootErrored) { 26414 workInProgressRootExitStatus = RootSuspendedWithDelay; 26415 } // Check if there are updates that we skipped tree that might have unblocked 26416 // this render. 26417 26418 26419 if (workInProgressRoot !== null && (includesNonIdleWork(workInProgressRootSkippedLanes) || includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes))) { 26420 // Mark the current render as suspended so that we switch to working on 26421 // the updates that were skipped. Usually we only suspend at the end of 26422 // the render phase. 26423 // TODO: We should probably always mark the root as suspended immediately 26424 // (inside this function), since by suspending at the end of the render 26425 // phase introduces a potential mistake where we suspend lanes that were 26426 // pinged or updated while we were rendering. 26427 markRootSuspended$1(workInProgressRoot, workInProgressRootRenderLanes); 26428 } 26429 } 26430 function renderDidError(error) { 26431 if (workInProgressRootExitStatus !== RootSuspendedWithDelay) { 26432 workInProgressRootExitStatus = RootErrored; 26433 } 26434 26435 if (workInProgressRootConcurrentErrors === null) { 26436 workInProgressRootConcurrentErrors = [error]; 26437 } else { 26438 workInProgressRootConcurrentErrors.push(error); 26439 } 26440 } // Called during render to determine if anything has suspended. 26441 // Returns false if we're not sure. 26442 26443 function renderHasNotSuspendedYet() { 26444 // If something errored or completed, we can't really be sure, 26445 // so those are false. 26446 return workInProgressRootExitStatus === RootInProgress; 26447 } 26448 26449 function renderRootSync(root, lanes) { 26450 var prevExecutionContext = executionContext; 26451 executionContext |= RenderContext; 26452 var prevDispatcher = pushDispatcher(); // If the root or lanes have changed, throw out the existing stack 26453 // and prepare a fresh one. Otherwise we'll continue where we left off. 26454 26455 if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { 26456 { 26457 if (isDevToolsPresent) { 26458 var memoizedUpdaters = root.memoizedUpdaters; 26459 26460 if (memoizedUpdaters.size > 0) { 26461 restorePendingUpdaters(root, workInProgressRootRenderLanes); 26462 memoizedUpdaters.clear(); 26463 } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set. 26464 // If we bailout on this work, we'll move them back (like above). 26465 // It's important to move them now in case the work spawns more work at the same priority with different updaters. 26466 // That way we can keep the current update and future updates separate. 26467 26468 26469 movePendingFibersToMemoized(root, lanes); 26470 } 26471 } 26472 26473 workInProgressTransitions = getTransitionsForLanes(); 26474 prepareFreshStack(root, lanes); 26475 } 26476 26477 { 26478 markRenderStarted(lanes); 26479 } 26480 26481 do { 26482 try { 26483 workLoopSync(); 26484 break; 26485 } catch (thrownValue) { 26486 handleError(root, thrownValue); 26487 } 26488 } while (true); 26489 26490 resetContextDependencies(); 26491 executionContext = prevExecutionContext; 26492 popDispatcher(prevDispatcher); 26493 26494 if (workInProgress !== null) { 26495 // This is a sync render, so we should have finished the whole tree. 26496 throw new Error('Cannot commit an incomplete root. This error is likely caused by a ' + 'bug in React. Please file an issue.'); 26497 } 26498 26499 { 26500 markRenderStopped(); 26501 } // Set this to null to indicate there's no in-progress render. 26502 26503 26504 workInProgressRoot = null; 26505 workInProgressRootRenderLanes = NoLanes; 26506 return workInProgressRootExitStatus; 26507 } // The work loop is an extremely hot path. Tell Closure not to inline it. 26508 26509 /** @noinline */ 26510 26511 26512 function workLoopSync() { 26513 // Already timed out, so perform work without checking if we need to yield. 26514 while (workInProgress !== null) { 26515 performUnitOfWork(workInProgress); 26516 } 26517 } 26518 26519 function renderRootConcurrent(root, lanes) { 26520 var prevExecutionContext = executionContext; 26521 executionContext |= RenderContext; 26522 var prevDispatcher = pushDispatcher(); // If the root or lanes have changed, throw out the existing stack 26523 // and prepare a fresh one. Otherwise we'll continue where we left off. 26524 26525 if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { 26526 { 26527 if (isDevToolsPresent) { 26528 var memoizedUpdaters = root.memoizedUpdaters; 26529 26530 if (memoizedUpdaters.size > 0) { 26531 restorePendingUpdaters(root, workInProgressRootRenderLanes); 26532 memoizedUpdaters.clear(); 26533 } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set. 26534 // If we bailout on this work, we'll move them back (like above). 26535 // It's important to move them now in case the work spawns more work at the same priority with different updaters. 26536 // That way we can keep the current update and future updates separate. 26537 26538 26539 movePendingFibersToMemoized(root, lanes); 26540 } 26541 } 26542 26543 workInProgressTransitions = getTransitionsForLanes(); 26544 resetRenderTimer(); 26545 prepareFreshStack(root, lanes); 26546 } 26547 26548 { 26549 markRenderStarted(lanes); 26550 } 26551 26552 do { 26553 try { 26554 workLoopConcurrent(); 26555 break; 26556 } catch (thrownValue) { 26557 handleError(root, thrownValue); 26558 } 26559 } while (true); 26560 26561 resetContextDependencies(); 26562 popDispatcher(prevDispatcher); 26563 executionContext = prevExecutionContext; 26564 26565 26566 if (workInProgress !== null) { 26567 // Still work remaining. 26568 { 26569 markRenderYielded(); 26570 } 26571 26572 return RootInProgress; 26573 } else { 26574 // Completed the tree. 26575 { 26576 markRenderStopped(); 26577 } // Set this to null to indicate there's no in-progress render. 26578 26579 26580 workInProgressRoot = null; 26581 workInProgressRootRenderLanes = NoLanes; // Return the final exit status. 26582 26583 return workInProgressRootExitStatus; 26584 } 26585 } 26586 /** @noinline */ 26587 26588 26589 function workLoopConcurrent() { 26590 // Perform work until Scheduler asks us to yield 26591 while (workInProgress !== null && !shouldYield()) { 26592 performUnitOfWork(workInProgress); 26593 } 26594 } 26595 26596 function performUnitOfWork(unitOfWork) { 26597 // The current, flushed, state of this fiber is the alternate. Ideally 26598 // nothing should rely on this, but relying on it here means that we don't 26599 // need an additional field on the work in progress. 26600 var current = unitOfWork.alternate; 26601 setCurrentFiber(unitOfWork); 26602 var next; 26603 26604 if ( (unitOfWork.mode & ProfileMode) !== NoMode) { 26605 startProfilerTimer(unitOfWork); 26606 next = beginWork$1(current, unitOfWork, subtreeRenderLanes); 26607 stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); 26608 } else { 26609 next = beginWork$1(current, unitOfWork, subtreeRenderLanes); 26610 } 26611 26612 resetCurrentFiber(); 26613 unitOfWork.memoizedProps = unitOfWork.pendingProps; 26614 26615 if (next === null) { 26616 // If this doesn't spawn new work, complete the current work. 26617 completeUnitOfWork(unitOfWork); 26618 } else { 26619 workInProgress = next; 26620 } 26621 26622 ReactCurrentOwner$2.current = null; 26623 } 26624 26625 function completeUnitOfWork(unitOfWork) { 26626 // Attempt to complete the current unit of work, then move to the next 26627 // sibling. If there are no more siblings, return to the parent fiber. 26628 var completedWork = unitOfWork; 26629 26630 do { 26631 // The current, flushed, state of this fiber is the alternate. Ideally 26632 // nothing should rely on this, but relying on it here means that we don't 26633 // need an additional field on the work in progress. 26634 var current = completedWork.alternate; 26635 var returnFiber = completedWork.return; // Check if the work completed or if something threw. 26636 26637 if ((completedWork.flags & Incomplete) === NoFlags) { 26638 setCurrentFiber(completedWork); 26639 var next = void 0; 26640 26641 if ( (completedWork.mode & ProfileMode) === NoMode) { 26642 next = completeWork(current, completedWork, subtreeRenderLanes); 26643 } else { 26644 startProfilerTimer(completedWork); 26645 next = completeWork(current, completedWork, subtreeRenderLanes); // Update render duration assuming we didn't error. 26646 26647 stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); 26648 } 26649 26650 resetCurrentFiber(); 26651 26652 if (next !== null) { 26653 // Completing this fiber spawned new work. Work on that next. 26654 workInProgress = next; 26655 return; 26656 } 26657 } else { 26658 // This fiber did not complete because something threw. Pop values off 26659 // the stack without entering the complete phase. If this is a boundary, 26660 // capture values if possible. 26661 var _next = unwindWork(current, completedWork); // Because this fiber did not complete, don't reset its lanes. 26662 26663 26664 if (_next !== null) { 26665 // If completing this work spawned new work, do that next. We'll come 26666 // back here again. 26667 // Since we're restarting, remove anything that is not a host effect 26668 // from the effect tag. 26669 _next.flags &= HostEffectMask; 26670 workInProgress = _next; 26671 return; 26672 } 26673 26674 if ( (completedWork.mode & ProfileMode) !== NoMode) { 26675 // Record the render duration for the fiber that errored. 26676 stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); // Include the time spent working on failed children before continuing. 26677 26678 var actualDuration = completedWork.actualDuration; 26679 var child = completedWork.child; 26680 26681 while (child !== null) { 26682 actualDuration += child.actualDuration; 26683 child = child.sibling; 26684 } 26685 26686 completedWork.actualDuration = actualDuration; 26687 } 26688 26689 if (returnFiber !== null) { 26690 // Mark the parent fiber as incomplete and clear its subtree flags. 26691 returnFiber.flags |= Incomplete; 26692 returnFiber.subtreeFlags = NoFlags; 26693 returnFiber.deletions = null; 26694 } else { 26695 // We've unwound all the way to the root. 26696 workInProgressRootExitStatus = RootDidNotComplete; 26697 workInProgress = null; 26698 return; 26699 } 26700 } 26701 26702 var siblingFiber = completedWork.sibling; 26703 26704 if (siblingFiber !== null) { 26705 // If there is more work to do in this returnFiber, do that next. 26706 workInProgress = siblingFiber; 26707 return; 26708 } // Otherwise, return to the parent 26709 26710 26711 completedWork = returnFiber; // Update the next thing we're working on in case something throws. 26712 26713 workInProgress = completedWork; 26714 } while (completedWork !== null); // We've reached the root. 26715 26716 26717 if (workInProgressRootExitStatus === RootInProgress) { 26718 workInProgressRootExitStatus = RootCompleted; 26719 } 26720 } 26721 26722 function commitRoot(root, recoverableErrors, transitions) { 26723 // TODO: This no longer makes any sense. We already wrap the mutation and 26724 // layout phases. Should be able to remove. 26725 var previousUpdateLanePriority = getCurrentUpdatePriority(); 26726 var prevTransition = ReactCurrentBatchConfig$3.transition; 26727 26728 try { 26729 ReactCurrentBatchConfig$3.transition = null; 26730 setCurrentUpdatePriority(DiscreteEventPriority); 26731 commitRootImpl(root, recoverableErrors, transitions, previousUpdateLanePriority); 26732 } finally { 26733 ReactCurrentBatchConfig$3.transition = prevTransition; 26734 setCurrentUpdatePriority(previousUpdateLanePriority); 26735 } 26736 26737 return null; 26738 } 26739 26740 function commitRootImpl(root, recoverableErrors, transitions, renderPriorityLevel) { 26741 do { 26742 // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which 26743 // means `flushPassiveEffects` will sometimes result in additional 26744 // passive effects. So we need to keep flushing in a loop until there are 26745 // no more pending effects. 26746 // TODO: Might be better if `flushPassiveEffects` did not automatically 26747 // flush synchronous work at the end, to avoid factoring hazards like this. 26748 flushPassiveEffects(); 26749 } while (rootWithPendingPassiveEffects !== null); 26750 26751 flushRenderPhaseStrictModeWarningsInDEV(); 26752 26753 if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { 26754 throw new Error('Should not already be working.'); 26755 } 26756 26757 var finishedWork = root.finishedWork; 26758 var lanes = root.finishedLanes; 26759 26760 { 26761 markCommitStarted(lanes); 26762 } 26763 26764 if (finishedWork === null) { 26765 26766 { 26767 markCommitStopped(); 26768 } 26769 26770 return null; 26771 } else { 26772 { 26773 if (lanes === NoLanes) { 26774 error('root.finishedLanes should not be empty during a commit. This is a ' + 'bug in React.'); 26775 } 26776 } 26777 } 26778 26779 root.finishedWork = null; 26780 root.finishedLanes = NoLanes; 26781 26782 if (finishedWork === root.current) { 26783 throw new Error('Cannot commit the same tree as before. This error is likely caused by ' + 'a bug in React. Please file an issue.'); 26784 } // commitRoot never returns a continuation; it always finishes synchronously. 26785 // So we can clear these now to allow a new callback to be scheduled. 26786 26787 26788 root.callbackNode = null; 26789 root.callbackPriority = NoLane; // Update the first and last pending times on this root. The new first 26790 // pending time is whatever is left on the root fiber. 26791 26792 var remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes); 26793 markRootFinished(root, remainingLanes); 26794 26795 if (root === workInProgressRoot) { 26796 // We can reset these now that they are finished. 26797 workInProgressRoot = null; 26798 workInProgress = null; 26799 workInProgressRootRenderLanes = NoLanes; 26800 } // If there are pending passive effects, schedule a callback to process them. 26801 // Do this as early as possible, so it is queued before anything else that 26802 // might get scheduled in the commit phase. (See #16714.) 26803 // TODO: Delete all other places that schedule the passive effect callback 26804 // They're redundant. 26805 26806 26807 if ((finishedWork.subtreeFlags & PassiveMask) !== NoFlags || (finishedWork.flags & PassiveMask) !== NoFlags) { 26808 if (!rootDoesHavePassiveEffects) { 26809 rootDoesHavePassiveEffects = true; 26810 // to store it in pendingPassiveTransitions until they get processed 26811 // We need to pass this through as an argument to commitRoot 26812 // because workInProgressTransitions might have changed between 26813 // the previous render and commit if we throttle the commit 26814 // with setTimeout 26815 26816 pendingPassiveTransitions = transitions; 26817 scheduleCallback$1(NormalPriority, function () { 26818 flushPassiveEffects(); // This render triggered passive effects: release the root cache pool 26819 // *after* passive effects fire to avoid freeing a cache pool that may 26820 // be referenced by a node in the tree (HostRoot, Cache boundary etc) 26821 26822 return null; 26823 }); 26824 } 26825 } // Check if there are any effects in the whole tree. 26826 // TODO: This is left over from the effect list implementation, where we had 26827 // to check for the existence of `firstEffect` to satisfy Flow. I think the 26828 // only other reason this optimization exists is because it affects profiling. 26829 // Reconsider whether this is necessary. 26830 26831 26832 var subtreeHasEffects = (finishedWork.subtreeFlags & (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== NoFlags; 26833 var rootHasEffect = (finishedWork.flags & (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== NoFlags; 26834 26835 if (subtreeHasEffects || rootHasEffect) { 26836 var prevTransition = ReactCurrentBatchConfig$3.transition; 26837 ReactCurrentBatchConfig$3.transition = null; 26838 var previousPriority = getCurrentUpdatePriority(); 26839 setCurrentUpdatePriority(DiscreteEventPriority); 26840 var prevExecutionContext = executionContext; 26841 executionContext |= CommitContext; // Reset this to null before calling lifecycles 26842 26843 ReactCurrentOwner$2.current = null; // The commit phase is broken into several sub-phases. We do a separate pass 26844 // of the effect list for each phase: all mutation effects come before all 26845 // layout effects, and so on. 26846 // The first phase a "before mutation" phase. We use this phase to read the 26847 // state of the host tree right before we mutate it. This is where 26848 // getSnapshotBeforeUpdate is called. 26849 26850 var shouldFireAfterActiveInstanceBlur = commitBeforeMutationEffects(root, finishedWork); 26851 26852 { 26853 // Mark the current commit time to be shared by all Profilers in this 26854 // batch. This enables them to be grouped later. 26855 recordCommitTime(); 26856 } 26857 26858 26859 commitMutationEffects(root, finishedWork, lanes); 26860 26861 resetAfterCommit(root.containerInfo); // The work-in-progress tree is now the current tree. This must come after 26862 // the mutation phase, so that the previous tree is still current during 26863 // componentWillUnmount, but before the layout phase, so that the finished 26864 // work is current during componentDidMount/Update. 26865 26866 root.current = finishedWork; // The next phase is the layout phase, where we call effects that read 26867 26868 { 26869 markLayoutEffectsStarted(lanes); 26870 } 26871 26872 commitLayoutEffects(finishedWork, root, lanes); 26873 26874 { 26875 markLayoutEffectsStopped(); 26876 } 26877 // opportunity to paint. 26878 26879 26880 requestPaint(); 26881 executionContext = prevExecutionContext; // Reset the priority to the previous non-sync value. 26882 26883 setCurrentUpdatePriority(previousPriority); 26884 ReactCurrentBatchConfig$3.transition = prevTransition; 26885 } else { 26886 // No effects. 26887 root.current = finishedWork; // Measure these anyway so the flamegraph explicitly shows that there were 26888 // no effects. 26889 // TODO: Maybe there's a better way to report this. 26890 26891 { 26892 recordCommitTime(); 26893 } 26894 } 26895 26896 var rootDidHavePassiveEffects = rootDoesHavePassiveEffects; 26897 26898 if (rootDoesHavePassiveEffects) { 26899 // This commit has passive effects. Stash a reference to them. But don't 26900 // schedule a callback until after flushing layout work. 26901 rootDoesHavePassiveEffects = false; 26902 rootWithPendingPassiveEffects = root; 26903 pendingPassiveEffectsLanes = lanes; 26904 } else { 26905 26906 { 26907 nestedPassiveUpdateCount = 0; 26908 rootWithPassiveNestedUpdates = null; 26909 } 26910 } // Read this again, since an effect might have updated it 26911 26912 26913 remainingLanes = root.pendingLanes; // Check if there's remaining work on this root 26914 // TODO: This is part of the `componentDidCatch` implementation. Its purpose 26915 // is to detect whether something might have called setState inside 26916 // `componentDidCatch`. The mechanism is known to be flawed because `setState` 26917 // inside `componentDidCatch` is itself flawed — that's why we recommend 26918 // `getDerivedStateFromError` instead. However, it could be improved by 26919 // checking if remainingLanes includes Sync work, instead of whether there's 26920 // any work remaining at all (which would also include stuff like Suspense 26921 // retries or transitions). It's been like this for a while, though, so fixing 26922 // it probably isn't that urgent. 26923 26924 if (remainingLanes === NoLanes) { 26925 // If there's no remaining work, we can clear the set of already failed 26926 // error boundaries. 26927 legacyErrorBoundariesThatAlreadyFailed = null; 26928 } 26929 26930 { 26931 if (!rootDidHavePassiveEffects) { 26932 commitDoubleInvokeEffectsInDEV(root.current, false); 26933 } 26934 } 26935 26936 onCommitRoot(finishedWork.stateNode, renderPriorityLevel); 26937 26938 { 26939 if (isDevToolsPresent) { 26940 root.memoizedUpdaters.clear(); 26941 } 26942 } 26943 26944 { 26945 onCommitRoot$1(); 26946 } // Always call this before exiting `commitRoot`, to ensure that any 26947 // additional work on this root is scheduled. 26948 26949 26950 ensureRootIsScheduled(root, now()); 26951 26952 if (recoverableErrors !== null) { 26953 // There were errors during this render, but recovered from them without 26954 // needing to surface it to the UI. We log them here. 26955 var onRecoverableError = root.onRecoverableError; 26956 26957 for (var i = 0; i < recoverableErrors.length; i++) { 26958 var recoverableError = recoverableErrors[i]; 26959 var componentStack = recoverableError.stack; 26960 var digest = recoverableError.digest; 26961 onRecoverableError(recoverableError.value, { 26962 componentStack: componentStack, 26963 digest: digest 26964 }); 26965 } 26966 } 26967 26968 if (hasUncaughtError) { 26969 hasUncaughtError = false; 26970 var error$1 = firstUncaughtError; 26971 firstUncaughtError = null; 26972 throw error$1; 26973 } // If the passive effects are the result of a discrete render, flush them 26974 // synchronously at the end of the current task so that the result is 26975 // immediately observable. Otherwise, we assume that they are not 26976 // order-dependent and do not need to be observed by external systems, so we 26977 // can wait until after paint. 26978 // TODO: We can optimize this by not scheduling the callback earlier. Since we 26979 // currently schedule the callback in multiple places, will wait until those 26980 // are consolidated. 26981 26982 26983 if (includesSomeLane(pendingPassiveEffectsLanes, SyncLane) && root.tag !== LegacyRoot) { 26984 flushPassiveEffects(); 26985 } // Read this again, since a passive effect might have updated it 26986 26987 26988 remainingLanes = root.pendingLanes; 26989 26990 if (includesSomeLane(remainingLanes, SyncLane)) { 26991 { 26992 markNestedUpdateScheduled(); 26993 } // Count the number of times the root synchronously re-renders without 26994 // finishing. If there are too many, it indicates an infinite update loop. 26995 26996 26997 if (root === rootWithNestedUpdates) { 26998 nestedUpdateCount++; 26999 } else { 27000 nestedUpdateCount = 0; 27001 rootWithNestedUpdates = root; 27002 } 27003 } else { 27004 nestedUpdateCount = 0; 27005 } // If layout work was scheduled, flush it now. 27006 27007 27008 flushSyncCallbacks(); 27009 27010 { 27011 markCommitStopped(); 27012 } 27013 27014 return null; 27015 } 27016 27017 function flushPassiveEffects() { 27018 // Returns whether passive effects were flushed. 27019 // TODO: Combine this check with the one in flushPassiveEFfectsImpl. We should 27020 // probably just combine the two functions. I believe they were only separate 27021 // in the first place because we used to wrap it with 27022 // `Scheduler.runWithPriority`, which accepts a function. But now we track the 27023 // priority within React itself, so we can mutate the variable directly. 27024 if (rootWithPendingPassiveEffects !== null) { 27025 var renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes); 27026 var priority = lowerEventPriority(DefaultEventPriority, renderPriority); 27027 var prevTransition = ReactCurrentBatchConfig$3.transition; 27028 var previousPriority = getCurrentUpdatePriority(); 27029 27030 try { 27031 ReactCurrentBatchConfig$3.transition = null; 27032 setCurrentUpdatePriority(priority); 27033 return flushPassiveEffectsImpl(); 27034 } finally { 27035 setCurrentUpdatePriority(previousPriority); 27036 ReactCurrentBatchConfig$3.transition = prevTransition; // Once passive effects have run for the tree - giving components a 27037 } 27038 } 27039 27040 return false; 27041 } 27042 function enqueuePendingPassiveProfilerEffect(fiber) { 27043 { 27044 pendingPassiveProfilerEffects.push(fiber); 27045 27046 if (!rootDoesHavePassiveEffects) { 27047 rootDoesHavePassiveEffects = true; 27048 scheduleCallback$1(NormalPriority, function () { 27049 flushPassiveEffects(); 27050 return null; 27051 }); 27052 } 27053 } 27054 } 27055 27056 function flushPassiveEffectsImpl() { 27057 if (rootWithPendingPassiveEffects === null) { 27058 return false; 27059 } // Cache and clear the transitions flag 27060 27061 27062 var transitions = pendingPassiveTransitions; 27063 pendingPassiveTransitions = null; 27064 var root = rootWithPendingPassiveEffects; 27065 var lanes = pendingPassiveEffectsLanes; 27066 rootWithPendingPassiveEffects = null; // TODO: This is sometimes out of sync with rootWithPendingPassiveEffects. 27067 // Figure out why and fix it. It's not causing any known issues (probably 27068 // because it's only used for profiling), but it's a refactor hazard. 27069 27070 pendingPassiveEffectsLanes = NoLanes; 27071 27072 if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { 27073 throw new Error('Cannot flush passive effects while already rendering.'); 27074 } 27075 27076 { 27077 isFlushingPassiveEffects = true; 27078 didScheduleUpdateDuringPassiveEffects = false; 27079 } 27080 27081 { 27082 markPassiveEffectsStarted(lanes); 27083 } 27084 27085 var prevExecutionContext = executionContext; 27086 executionContext |= CommitContext; 27087 commitPassiveUnmountEffects(root.current); 27088 commitPassiveMountEffects(root, root.current, lanes, transitions); // TODO: Move to commitPassiveMountEffects 27089 27090 { 27091 var profilerEffects = pendingPassiveProfilerEffects; 27092 pendingPassiveProfilerEffects = []; 27093 27094 for (var i = 0; i < profilerEffects.length; i++) { 27095 var _fiber = profilerEffects[i]; 27096 commitPassiveEffectDurations(root, _fiber); 27097 } 27098 } 27099 27100 { 27101 markPassiveEffectsStopped(); 27102 } 27103 27104 { 27105 commitDoubleInvokeEffectsInDEV(root.current, true); 27106 } 27107 27108 executionContext = prevExecutionContext; 27109 flushSyncCallbacks(); 27110 27111 { 27112 // If additional passive effects were scheduled, increment a counter. If this 27113 // exceeds the limit, we'll fire a warning. 27114 if (didScheduleUpdateDuringPassiveEffects) { 27115 if (root === rootWithPassiveNestedUpdates) { 27116 nestedPassiveUpdateCount++; 27117 } else { 27118 nestedPassiveUpdateCount = 0; 27119 rootWithPassiveNestedUpdates = root; 27120 } 27121 } else { 27122 nestedPassiveUpdateCount = 0; 27123 } 27124 27125 isFlushingPassiveEffects = false; 27126 didScheduleUpdateDuringPassiveEffects = false; 27127 } // TODO: Move to commitPassiveMountEffects 27128 27129 27130 onPostCommitRoot(root); 27131 27132 { 27133 var stateNode = root.current.stateNode; 27134 stateNode.effectDuration = 0; 27135 stateNode.passiveEffectDuration = 0; 27136 } 27137 27138 return true; 27139 } 27140 27141 function isAlreadyFailedLegacyErrorBoundary(instance) { 27142 return legacyErrorBoundariesThatAlreadyFailed !== null && legacyErrorBoundariesThatAlreadyFailed.has(instance); 27143 } 27144 function markLegacyErrorBoundaryAsFailed(instance) { 27145 if (legacyErrorBoundariesThatAlreadyFailed === null) { 27146 legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); 27147 } else { 27148 legacyErrorBoundariesThatAlreadyFailed.add(instance); 27149 } 27150 } 27151 27152 function prepareToThrowUncaughtError(error) { 27153 if (!hasUncaughtError) { 27154 hasUncaughtError = true; 27155 firstUncaughtError = error; 27156 } 27157 } 27158 27159 var onUncaughtError = prepareToThrowUncaughtError; 27160 27161 function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { 27162 var errorInfo = createCapturedValueAtFiber(error, sourceFiber); 27163 var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane); 27164 var root = enqueueUpdate(rootFiber, update, SyncLane); 27165 var eventTime = requestEventTime(); 27166 27167 if (root !== null) { 27168 markRootUpdated(root, SyncLane, eventTime); 27169 ensureRootIsScheduled(root, eventTime); 27170 } 27171 } 27172 27173 function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error$1) { 27174 { 27175 reportUncaughtErrorInDEV(error$1); 27176 setIsRunningInsertionEffect(false); 27177 } 27178 27179 if (sourceFiber.tag === HostRoot) { 27180 // Error was thrown at the root. There is no parent, so the root 27181 // itself should capture it. 27182 captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error$1); 27183 return; 27184 } 27185 27186 var fiber = null; 27187 27188 { 27189 fiber = nearestMountedAncestor; 27190 } 27191 27192 while (fiber !== null) { 27193 if (fiber.tag === HostRoot) { 27194 captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error$1); 27195 return; 27196 } else if (fiber.tag === ClassComponent) { 27197 var ctor = fiber.type; 27198 var instance = fiber.stateNode; 27199 27200 if (typeof ctor.getDerivedStateFromError === 'function' || typeof instance.componentDidCatch === 'function' && !isAlreadyFailedLegacyErrorBoundary(instance)) { 27201 var errorInfo = createCapturedValueAtFiber(error$1, sourceFiber); 27202 var update = createClassErrorUpdate(fiber, errorInfo, SyncLane); 27203 var root = enqueueUpdate(fiber, update, SyncLane); 27204 var eventTime = requestEventTime(); 27205 27206 if (root !== null) { 27207 markRootUpdated(root, SyncLane, eventTime); 27208 ensureRootIsScheduled(root, eventTime); 27209 } 27210 27211 return; 27212 } 27213 } 27214 27215 fiber = fiber.return; 27216 } 27217 27218 { 27219 // TODO: Until we re-land skipUnmountedBoundaries (see #20147), this warning 27220 // will fire for errors that are thrown by destroy functions inside deleted 27221 // trees. What it should instead do is propagate the error to the parent of 27222 // the deleted tree. In the meantime, do not add this warning to the 27223 // allowlist; this is only for our internal use. 27224 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); 27225 } 27226 } 27227 function pingSuspendedRoot(root, wakeable, pingedLanes) { 27228 var pingCache = root.pingCache; 27229 27230 if (pingCache !== null) { 27231 // The wakeable resolved, so we no longer need to memoize, because it will 27232 // never be thrown again. 27233 pingCache.delete(wakeable); 27234 } 27235 27236 var eventTime = requestEventTime(); 27237 markRootPinged(root, pingedLanes); 27238 warnIfSuspenseResolutionNotWrappedWithActDEV(root); 27239 27240 if (workInProgressRoot === root && isSubsetOfLanes(workInProgressRootRenderLanes, pingedLanes)) { 27241 // Received a ping at the same priority level at which we're currently 27242 // rendering. We might want to restart this render. This should mirror 27243 // the logic of whether or not a root suspends once it completes. 27244 // TODO: If we're rendering sync either due to Sync, Batched or expired, 27245 // we should probably never restart. 27246 // If we're suspended with delay, or if it's a retry, we'll always suspend 27247 // so we can always restart. 27248 if (workInProgressRootExitStatus === RootSuspendedWithDelay || workInProgressRootExitStatus === RootSuspended && includesOnlyRetries(workInProgressRootRenderLanes) && now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) { 27249 // Restart from the root. 27250 prepareFreshStack(root, NoLanes); 27251 } else { 27252 // Even though we can't restart right now, we might get an 27253 // opportunity later. So we mark this render as having a ping. 27254 workInProgressRootPingedLanes = mergeLanes(workInProgressRootPingedLanes, pingedLanes); 27255 } 27256 } 27257 27258 ensureRootIsScheduled(root, eventTime); 27259 } 27260 27261 function retryTimedOutBoundary(boundaryFiber, retryLane) { 27262 // The boundary fiber (a Suspense component or SuspenseList component) 27263 // previously was rendered in its fallback state. One of the promises that 27264 // suspended it has resolved, which means at least part of the tree was 27265 // likely unblocked. Try rendering again, at a new lanes. 27266 if (retryLane === NoLane) { 27267 // TODO: Assign this to `suspenseState.retryLane`? to avoid 27268 // unnecessary entanglement? 27269 retryLane = requestRetryLane(boundaryFiber); 27270 } // TODO: Special case idle priority? 27271 27272 27273 var eventTime = requestEventTime(); 27274 var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); 27275 27276 if (root !== null) { 27277 markRootUpdated(root, retryLane, eventTime); 27278 ensureRootIsScheduled(root, eventTime); 27279 } 27280 } 27281 27282 function retryDehydratedSuspenseBoundary(boundaryFiber) { 27283 var suspenseState = boundaryFiber.memoizedState; 27284 var retryLane = NoLane; 27285 27286 if (suspenseState !== null) { 27287 retryLane = suspenseState.retryLane; 27288 } 27289 27290 retryTimedOutBoundary(boundaryFiber, retryLane); 27291 } 27292 function resolveRetryWakeable(boundaryFiber, wakeable) { 27293 var retryLane = NoLane; // Default 27294 27295 var retryCache; 27296 27297 switch (boundaryFiber.tag) { 27298 case SuspenseComponent: 27299 retryCache = boundaryFiber.stateNode; 27300 var suspenseState = boundaryFiber.memoizedState; 27301 27302 if (suspenseState !== null) { 27303 retryLane = suspenseState.retryLane; 27304 } 27305 27306 break; 27307 27308 case SuspenseListComponent: 27309 retryCache = boundaryFiber.stateNode; 27310 break; 27311 27312 default: 27313 throw new Error('Pinged unknown suspense boundary type. ' + 'This is probably a bug in React.'); 27314 } 27315 27316 if (retryCache !== null) { 27317 // The wakeable resolved, so we no longer need to memoize, because it will 27318 // never be thrown again. 27319 retryCache.delete(wakeable); 27320 } 27321 27322 retryTimedOutBoundary(boundaryFiber, retryLane); 27323 } // Computes the next Just Noticeable Difference (JND) boundary. 27324 // The theory is that a person can't tell the difference between small differences in time. 27325 // Therefore, if we wait a bit longer than necessary that won't translate to a noticeable 27326 // difference in the experience. However, waiting for longer might mean that we can avoid 27327 // showing an intermediate loading state. The longer we have already waited, the harder it 27328 // is to tell small differences in time. Therefore, the longer we've already waited, 27329 // the longer we can wait additionally. At some point we have to give up though. 27330 // We pick a train model where the next boundary commits at a consistent schedule. 27331 // These particular numbers are vague estimates. We expect to adjust them based on research. 27332 27333 function jnd(timeElapsed) { 27334 return timeElapsed < 120 ? 120 : timeElapsed < 480 ? 480 : timeElapsed < 1080 ? 1080 : timeElapsed < 1920 ? 1920 : timeElapsed < 3000 ? 3000 : timeElapsed < 4320 ? 4320 : ceil(timeElapsed / 1960) * 1960; 27335 } 27336 27337 function checkForNestedUpdates() { 27338 if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { 27339 nestedUpdateCount = 0; 27340 rootWithNestedUpdates = null; 27341 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.'); 27342 } 27343 27344 { 27345 if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { 27346 nestedPassiveUpdateCount = 0; 27347 rootWithPassiveNestedUpdates = null; 27348 27349 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.'); 27350 } 27351 } 27352 } 27353 27354 function flushRenderPhaseStrictModeWarningsInDEV() { 27355 { 27356 ReactStrictModeWarnings.flushLegacyContextWarning(); 27357 27358 { 27359 ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); 27360 } 27361 } 27362 } 27363 27364 function commitDoubleInvokeEffectsInDEV(fiber, hasPassiveEffects) { 27365 { 27366 // TODO (StrictEffects) Should we set a marker on the root if it contains strict effects 27367 // so we don't traverse unnecessarily? similar to subtreeFlags but just at the root level. 27368 // Maybe not a big deal since this is DEV only behavior. 27369 setCurrentFiber(fiber); 27370 invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectUnmountInDEV); 27371 27372 if (hasPassiveEffects) { 27373 invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectUnmountInDEV); 27374 } 27375 27376 invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectMountInDEV); 27377 27378 if (hasPassiveEffects) { 27379 invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectMountInDEV); 27380 } 27381 27382 resetCurrentFiber(); 27383 } 27384 } 27385 27386 function invokeEffectsInDev(firstChild, fiberFlags, invokeEffectFn) { 27387 { 27388 // We don't need to re-check StrictEffectsMode here. 27389 // This function is only called if that check has already passed. 27390 var current = firstChild; 27391 var subtreeRoot = null; 27392 27393 while (current !== null) { 27394 var primarySubtreeFlag = current.subtreeFlags & fiberFlags; 27395 27396 if (current !== subtreeRoot && current.child !== null && primarySubtreeFlag !== NoFlags) { 27397 current = current.child; 27398 } else { 27399 if ((current.flags & fiberFlags) !== NoFlags) { 27400 invokeEffectFn(current); 27401 } 27402 27403 if (current.sibling !== null) { 27404 current = current.sibling; 27405 } else { 27406 current = subtreeRoot = current.return; 27407 } 27408 } 27409 } 27410 } 27411 } 27412 27413 var didWarnStateUpdateForNotYetMountedComponent = null; 27414 function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { 27415 { 27416 if ((executionContext & RenderContext) !== NoContext) { 27417 // We let the other warning about render phase updates deal with this one. 27418 return; 27419 } 27420 27421 if (!(fiber.mode & ConcurrentMode)) { 27422 return; 27423 } 27424 27425 var tag = fiber.tag; 27426 27427 if (tag !== IndeterminateComponent && tag !== HostRoot && tag !== ClassComponent && tag !== FunctionComponent && tag !== ForwardRef && tag !== MemoComponent && tag !== SimpleMemoComponent) { 27428 // Only warn for user-defined components, not internal ones like Suspense. 27429 return; 27430 } // We show the whole stack but dedupe on the top component's name because 27431 // the problematic code almost always lies inside that component. 27432 27433 27434 var componentName = getComponentNameFromFiber(fiber) || 'ReactComponent'; 27435 27436 if (didWarnStateUpdateForNotYetMountedComponent !== null) { 27437 if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) { 27438 return; 27439 } 27440 27441 didWarnStateUpdateForNotYetMountedComponent.add(componentName); 27442 } else { 27443 didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]); 27444 } 27445 27446 var previousFiber = current; 27447 27448 try { 27449 setCurrentFiber(fiber); 27450 27451 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.'); 27452 } finally { 27453 if (previousFiber) { 27454 setCurrentFiber(fiber); 27455 } else { 27456 resetCurrentFiber(); 27457 } 27458 } 27459 } 27460 } 27461 var beginWork$1; 27462 27463 { 27464 var dummyFiber = null; 27465 27466 beginWork$1 = function (current, unitOfWork, lanes) { 27467 // If a component throws an error, we replay it again in a synchronously 27468 // dispatched event, so that the debugger will treat it as an uncaught 27469 // error See ReactErrorUtils for more information. 27470 // Before entering the begin phase, copy the work-in-progress onto a dummy 27471 // fiber. If beginWork throws, we'll use this to reset the state. 27472 var originalWorkInProgressCopy = assignFiberPropertiesInDEV(dummyFiber, unitOfWork); 27473 27474 try { 27475 return beginWork(current, unitOfWork, lanes); 27476 } catch (originalError) { 27477 if (didSuspendOrErrorWhileHydratingDEV() || originalError !== null && typeof originalError === 'object' && typeof originalError.then === 'function') { 27478 // Don't replay promises. 27479 // Don't replay errors if we are hydrating and have already suspended or handled an error 27480 throw originalError; 27481 } // Keep this code in sync with handleError; any changes here must have 27482 // corresponding changes there. 27483 27484 27485 resetContextDependencies(); 27486 resetHooksAfterThrow(); // Don't reset current debug fiber, since we're about to work on the 27487 // same fiber again. 27488 // Unwind the failed stack frame 27489 27490 unwindInterruptedWork(current, unitOfWork); // Restore the original properties of the fiber. 27491 27492 assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); 27493 27494 if ( unitOfWork.mode & ProfileMode) { 27495 // Reset the profiler timer. 27496 startProfilerTimer(unitOfWork); 27497 } // Run beginWork again. 27498 27499 27500 invokeGuardedCallback(null, beginWork, null, current, unitOfWork, lanes); 27501 27502 if (hasCaughtError()) { 27503 var replayError = clearCaughtError(); 27504 27505 if (typeof replayError === 'object' && replayError !== null && replayError._suppressLogging && typeof originalError === 'object' && originalError !== null && !originalError._suppressLogging) { 27506 // If suppressed, let the flag carry over to the original error which is the one we'll rethrow. 27507 originalError._suppressLogging = true; 27508 } 27509 } // We always throw the original error in case the second render pass is not idempotent. 27510 // This can happen if a memoized function or CommonJS module doesn't throw after first invocation. 27511 27512 27513 throw originalError; 27514 } 27515 }; 27516 } 27517 27518 var didWarnAboutUpdateInRender = false; 27519 var didWarnAboutUpdateInRenderForAnotherComponent; 27520 27521 { 27522 didWarnAboutUpdateInRenderForAnotherComponent = new Set(); 27523 } 27524 27525 function warnAboutRenderPhaseUpdatesInDEV(fiber) { 27526 { 27527 if (isRendering && !getIsUpdatingOpaqueValueInRenderPhaseInDEV()) { 27528 switch (fiber.tag) { 27529 case FunctionComponent: 27530 case ForwardRef: 27531 case SimpleMemoComponent: 27532 { 27533 var renderingComponentName = workInProgress && getComponentNameFromFiber(workInProgress) || 'Unknown'; // Dedupe by the rendering component because it's the one that needs to be fixed. 27534 27535 var dedupeKey = renderingComponentName; 27536 27537 if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) { 27538 didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey); 27539 var setStateComponentName = getComponentNameFromFiber(fiber) || 'Unknown'; 27540 27541 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); 27542 } 27543 27544 break; 27545 } 27546 27547 case ClassComponent: 27548 { 27549 if (!didWarnAboutUpdateInRender) { 27550 error('Cannot update during an existing state transition (such as ' + 'within `render`). Render methods should be a pure ' + 'function of props and state.'); 27551 27552 didWarnAboutUpdateInRender = true; 27553 } 27554 27555 break; 27556 } 27557 } 27558 } 27559 } 27560 } 27561 27562 function restorePendingUpdaters(root, lanes) { 27563 { 27564 if (isDevToolsPresent) { 27565 var memoizedUpdaters = root.memoizedUpdaters; 27566 memoizedUpdaters.forEach(function (schedulingFiber) { 27567 addFiberToLanesMap(root, schedulingFiber, lanes); 27568 }); // This function intentionally does not clear memoized updaters. 27569 // Those may still be relevant to the current commit 27570 // and a future one (e.g. Suspense). 27571 } 27572 } 27573 } 27574 var fakeActCallbackNode = {}; 27575 27576 function scheduleCallback$1(priorityLevel, callback) { 27577 { 27578 // If we're currently inside an `act` scope, bypass Scheduler and push to 27579 // the `act` queue instead. 27580 var actQueue = ReactCurrentActQueue$1.current; 27581 27582 if (actQueue !== null) { 27583 actQueue.push(callback); 27584 return fakeActCallbackNode; 27585 } else { 27586 return scheduleCallback(priorityLevel, callback); 27587 } 27588 } 27589 } 27590 27591 function cancelCallback$1(callbackNode) { 27592 if ( callbackNode === fakeActCallbackNode) { 27593 return; 27594 } // In production, always call Scheduler. This function will be stripped out. 27595 27596 27597 return cancelCallback(callbackNode); 27598 } 27599 27600 function shouldForceFlushFallbacksInDEV() { 27601 // Never force flush in production. This function should get stripped out. 27602 return ReactCurrentActQueue$1.current !== null; 27603 } 27604 27605 function warnIfUpdatesNotWrappedWithActDEV(fiber) { 27606 { 27607 if (fiber.mode & ConcurrentMode) { 27608 if (!isConcurrentActEnvironment()) { 27609 // Not in an act environment. No need to warn. 27610 return; 27611 } 27612 } else { 27613 // Legacy mode has additional cases where we suppress a warning. 27614 if (!isLegacyActEnvironment()) { 27615 // Not in an act environment. No need to warn. 27616 return; 27617 } 27618 27619 if (executionContext !== NoContext) { 27620 // Legacy mode doesn't warn if the update is batched, i.e. 27621 // batchedUpdates or flushSync. 27622 return; 27623 } 27624 27625 if (fiber.tag !== FunctionComponent && fiber.tag !== ForwardRef && fiber.tag !== SimpleMemoComponent) { 27626 // For backwards compatibility with pre-hooks code, legacy mode only 27627 // warns for updates that originate from a hook. 27628 return; 27629 } 27630 } 27631 27632 if (ReactCurrentActQueue$1.current === null) { 27633 var previousFiber = current; 27634 27635 try { 27636 setCurrentFiber(fiber); 27637 27638 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)); 27639 } finally { 27640 if (previousFiber) { 27641 setCurrentFiber(fiber); 27642 } else { 27643 resetCurrentFiber(); 27644 } 27645 } 27646 } 27647 } 27648 } 27649 27650 function warnIfSuspenseResolutionNotWrappedWithActDEV(root) { 27651 { 27652 if (root.tag !== LegacyRoot && isConcurrentActEnvironment() && ReactCurrentActQueue$1.current === null) { 27653 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'); 27654 } 27655 } 27656 } 27657 27658 function setIsRunningInsertionEffect(isRunning) { 27659 { 27660 isRunningInsertionEffect = isRunning; 27661 } 27662 } 27663 27664 /* eslint-disable react-internal/prod-error-codes */ 27665 var resolveFamily = null; // $FlowFixMe Flow gets confused by a WeakSet feature check below. 27666 27667 var failedBoundaries = null; 27668 var setRefreshHandler = function (handler) { 27669 { 27670 resolveFamily = handler; 27671 } 27672 }; 27673 function resolveFunctionForHotReloading(type) { 27674 { 27675 if (resolveFamily === null) { 27676 // Hot reloading is disabled. 27677 return type; 27678 } 27679 27680 var family = resolveFamily(type); 27681 27682 if (family === undefined) { 27683 return type; 27684 } // Use the latest known implementation. 27685 27686 27687 return family.current; 27688 } 27689 } 27690 function resolveClassForHotReloading(type) { 27691 // No implementation differences. 27692 return resolveFunctionForHotReloading(type); 27693 } 27694 function resolveForwardRefForHotReloading(type) { 27695 { 27696 if (resolveFamily === null) { 27697 // Hot reloading is disabled. 27698 return type; 27699 } 27700 27701 var family = resolveFamily(type); 27702 27703 if (family === undefined) { 27704 // Check if we're dealing with a real forwardRef. Don't want to crash early. 27705 if (type !== null && type !== undefined && typeof type.render === 'function') { 27706 // ForwardRef is special because its resolved .type is an object, 27707 // but it's possible that we only have its inner render function in the map. 27708 // If that inner render function is different, we'll build a new forwardRef type. 27709 var currentRender = resolveFunctionForHotReloading(type.render); 27710 27711 if (type.render !== currentRender) { 27712 var syntheticType = { 27713 $$typeof: REACT_FORWARD_REF_TYPE, 27714 render: currentRender 27715 }; 27716 27717 if (type.displayName !== undefined) { 27718 syntheticType.displayName = type.displayName; 27719 } 27720 27721 return syntheticType; 27722 } 27723 } 27724 27725 return type; 27726 } // Use the latest known implementation. 27727 27728 27729 return family.current; 27730 } 27731 } 27732 function isCompatibleFamilyForHotReloading(fiber, element) { 27733 { 27734 if (resolveFamily === null) { 27735 // Hot reloading is disabled. 27736 return false; 27737 } 27738 27739 var prevType = fiber.elementType; 27740 var nextType = element.type; // If we got here, we know types aren't === equal. 27741 27742 var needsCompareFamilies = false; 27743 var $$typeofNextType = typeof nextType === 'object' && nextType !== null ? nextType.$$typeof : null; 27744 27745 switch (fiber.tag) { 27746 case ClassComponent: 27747 { 27748 if (typeof nextType === 'function') { 27749 needsCompareFamilies = true; 27750 } 27751 27752 break; 27753 } 27754 27755 case FunctionComponent: 27756 { 27757 if (typeof nextType === 'function') { 27758 needsCompareFamilies = true; 27759 } else if ($$typeofNextType === REACT_LAZY_TYPE) { 27760 // We don't know the inner type yet. 27761 // We're going to assume that the lazy inner type is stable, 27762 // and so it is sufficient to avoid reconciling it away. 27763 // We're not going to unwrap or actually use the new lazy type. 27764 needsCompareFamilies = true; 27765 } 27766 27767 break; 27768 } 27769 27770 case ForwardRef: 27771 { 27772 if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { 27773 needsCompareFamilies = true; 27774 } else if ($$typeofNextType === REACT_LAZY_TYPE) { 27775 needsCompareFamilies = true; 27776 } 27777 27778 break; 27779 } 27780 27781 case MemoComponent: 27782 case SimpleMemoComponent: 27783 { 27784 if ($$typeofNextType === REACT_MEMO_TYPE) { 27785 // TODO: if it was but can no longer be simple, 27786 // we shouldn't set this. 27787 needsCompareFamilies = true; 27788 } else if ($$typeofNextType === REACT_LAZY_TYPE) { 27789 needsCompareFamilies = true; 27790 } 27791 27792 break; 27793 } 27794 27795 default: 27796 return false; 27797 } // Check if both types have a family and it's the same one. 27798 27799 27800 if (needsCompareFamilies) { 27801 // Note: memo() and forwardRef() we'll compare outer rather than inner type. 27802 // This means both of them need to be registered to preserve state. 27803 // If we unwrapped and compared the inner types for wrappers instead, 27804 // then we would risk falsely saying two separate memo(Foo) 27805 // calls are equivalent because they wrap the same Foo function. 27806 var prevFamily = resolveFamily(prevType); 27807 27808 if (prevFamily !== undefined && prevFamily === resolveFamily(nextType)) { 27809 return true; 27810 } 27811 } 27812 27813 return false; 27814 } 27815 } 27816 function markFailedErrorBoundaryForHotReloading(fiber) { 27817 { 27818 if (resolveFamily === null) { 27819 // Hot reloading is disabled. 27820 return; 27821 } 27822 27823 if (typeof WeakSet !== 'function') { 27824 return; 27825 } 27826 27827 if (failedBoundaries === null) { 27828 failedBoundaries = new WeakSet(); 27829 } 27830 27831 failedBoundaries.add(fiber); 27832 } 27833 } 27834 var scheduleRefresh = function (root, update) { 27835 { 27836 if (resolveFamily === null) { 27837 // Hot reloading is disabled. 27838 return; 27839 } 27840 27841 var staleFamilies = update.staleFamilies, 27842 updatedFamilies = update.updatedFamilies; 27843 flushPassiveEffects(); 27844 flushSync(function () { 27845 scheduleFibersWithFamiliesRecursively(root.current, updatedFamilies, staleFamilies); 27846 }); 27847 } 27848 }; 27849 var scheduleRoot = function (root, element) { 27850 { 27851 if (root.context !== emptyContextObject) { 27852 // Super edge case: root has a legacy _renderSubtree context 27853 // but we don't know the parentComponent so we can't pass it. 27854 // Just ignore. We'll delete this with _renderSubtree code path later. 27855 return; 27856 } 27857 27858 flushPassiveEffects(); 27859 flushSync(function () { 27860 updateContainer(element, root, null, null); 27861 }); 27862 } 27863 }; 27864 27865 function scheduleFibersWithFamiliesRecursively(fiber, updatedFamilies, staleFamilies) { 27866 { 27867 var alternate = fiber.alternate, 27868 child = fiber.child, 27869 sibling = fiber.sibling, 27870 tag = fiber.tag, 27871 type = fiber.type; 27872 var candidateType = null; 27873 27874 switch (tag) { 27875 case FunctionComponent: 27876 case SimpleMemoComponent: 27877 case ClassComponent: 27878 candidateType = type; 27879 break; 27880 27881 case ForwardRef: 27882 candidateType = type.render; 27883 break; 27884 } 27885 27886 if (resolveFamily === null) { 27887 throw new Error('Expected resolveFamily to be set during hot reload.'); 27888 } 27889 27890 var needsRender = false; 27891 var needsRemount = false; 27892 27893 if (candidateType !== null) { 27894 var family = resolveFamily(candidateType); 27895 27896 if (family !== undefined) { 27897 if (staleFamilies.has(family)) { 27898 needsRemount = true; 27899 } else if (updatedFamilies.has(family)) { 27900 if (tag === ClassComponent) { 27901 needsRemount = true; 27902 } else { 27903 needsRender = true; 27904 } 27905 } 27906 } 27907 } 27908 27909 if (failedBoundaries !== null) { 27910 if (failedBoundaries.has(fiber) || alternate !== null && failedBoundaries.has(alternate)) { 27911 needsRemount = true; 27912 } 27913 } 27914 27915 if (needsRemount) { 27916 fiber._debugNeedsRemount = true; 27917 } 27918 27919 if (needsRemount || needsRender) { 27920 var _root = enqueueConcurrentRenderForLane(fiber, SyncLane); 27921 27922 if (_root !== null) { 27923 scheduleUpdateOnFiber(_root, fiber, SyncLane, NoTimestamp); 27924 } 27925 } 27926 27927 if (child !== null && !needsRemount) { 27928 scheduleFibersWithFamiliesRecursively(child, updatedFamilies, staleFamilies); 27929 } 27930 27931 if (sibling !== null) { 27932 scheduleFibersWithFamiliesRecursively(sibling, updatedFamilies, staleFamilies); 27933 } 27934 } 27935 } 27936 27937 var findHostInstancesForRefresh = function (root, families) { 27938 { 27939 var hostInstances = new Set(); 27940 var types = new Set(families.map(function (family) { 27941 return family.current; 27942 })); 27943 findHostInstancesForMatchingFibersRecursively(root.current, types, hostInstances); 27944 return hostInstances; 27945 } 27946 }; 27947 27948 function findHostInstancesForMatchingFibersRecursively(fiber, types, hostInstances) { 27949 { 27950 var child = fiber.child, 27951 sibling = fiber.sibling, 27952 tag = fiber.tag, 27953 type = fiber.type; 27954 var candidateType = null; 27955 27956 switch (tag) { 27957 case FunctionComponent: 27958 case SimpleMemoComponent: 27959 case ClassComponent: 27960 candidateType = type; 27961 break; 27962 27963 case ForwardRef: 27964 candidateType = type.render; 27965 break; 27966 } 27967 27968 var didMatch = false; 27969 27970 if (candidateType !== null) { 27971 if (types.has(candidateType)) { 27972 didMatch = true; 27973 } 27974 } 27975 27976 if (didMatch) { 27977 // We have a match. This only drills down to the closest host components. 27978 // There's no need to search deeper because for the purpose of giving 27979 // visual feedback, "flashing" outermost parent rectangles is sufficient. 27980 findHostInstancesForFiberShallowly(fiber, hostInstances); 27981 } else { 27982 // If there's no match, maybe there will be one further down in the child tree. 27983 if (child !== null) { 27984 findHostInstancesForMatchingFibersRecursively(child, types, hostInstances); 27985 } 27986 } 27987 27988 if (sibling !== null) { 27989 findHostInstancesForMatchingFibersRecursively(sibling, types, hostInstances); 27990 } 27991 } 27992 } 27993 27994 function findHostInstancesForFiberShallowly(fiber, hostInstances) { 27995 { 27996 var foundHostInstances = findChildHostInstancesForFiberShallowly(fiber, hostInstances); 27997 27998 if (foundHostInstances) { 27999 return; 28000 } // If we didn't find any host children, fallback to closest host parent. 28001 28002 28003 var node = fiber; 28004 28005 while (true) { 28006 switch (node.tag) { 28007 case HostComponent: 28008 hostInstances.add(node.stateNode); 28009 return; 28010 28011 case HostPortal: 28012 hostInstances.add(node.stateNode.containerInfo); 28013 return; 28014 28015 case HostRoot: 28016 hostInstances.add(node.stateNode.containerInfo); 28017 return; 28018 } 28019 28020 if (node.return === null) { 28021 throw new Error('Expected to reach root first.'); 28022 } 28023 28024 node = node.return; 28025 } 28026 } 28027 } 28028 28029 function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { 28030 { 28031 var node = fiber; 28032 var foundHostInstances = false; 28033 28034 while (true) { 28035 if (node.tag === HostComponent) { 28036 // We got a match. 28037 foundHostInstances = true; 28038 hostInstances.add(node.stateNode); // There may still be more, so keep searching. 28039 } else if (node.child !== null) { 28040 node.child.return = node; 28041 node = node.child; 28042 continue; 28043 } 28044 28045 if (node === fiber) { 28046 return foundHostInstances; 28047 } 28048 28049 while (node.sibling === null) { 28050 if (node.return === null || node.return === fiber) { 28051 return foundHostInstances; 28052 } 28053 28054 node = node.return; 28055 } 28056 28057 node.sibling.return = node.return; 28058 node = node.sibling; 28059 } 28060 } 28061 28062 return false; 28063 } 28064 28065 var hasBadMapPolyfill; 28066 28067 { 28068 hasBadMapPolyfill = false; 28069 28070 try { 28071 var nonExtensibleObject = Object.preventExtensions({}); 28072 /* eslint-disable no-new */ 28073 28074 new Map([[nonExtensibleObject, null]]); 28075 new Set([nonExtensibleObject]); 28076 /* eslint-enable no-new */ 28077 } catch (e) { 28078 // TODO: Consider warning about bad polyfills 28079 hasBadMapPolyfill = true; 28080 } 28081 } 28082 28083 function FiberNode(tag, pendingProps, key, mode) { 28084 // Instance 28085 this.tag = tag; 28086 this.key = key; 28087 this.elementType = null; 28088 this.type = null; 28089 this.stateNode = null; // Fiber 28090 28091 this.return = null; 28092 this.child = null; 28093 this.sibling = null; 28094 this.index = 0; 28095 this.ref = null; 28096 this.pendingProps = pendingProps; 28097 this.memoizedProps = null; 28098 this.updateQueue = null; 28099 this.memoizedState = null; 28100 this.dependencies = null; 28101 this.mode = mode; // Effects 28102 28103 this.flags = NoFlags; 28104 this.subtreeFlags = NoFlags; 28105 this.deletions = null; 28106 this.lanes = NoLanes; 28107 this.childLanes = NoLanes; 28108 this.alternate = null; 28109 28110 { 28111 // Note: The following is done to avoid a v8 performance cliff. 28112 // 28113 // Initializing the fields below to smis and later updating them with 28114 // double values will cause Fibers to end up having separate shapes. 28115 // This behavior/bug has something to do with Object.preventExtension(). 28116 // Fortunately this only impacts DEV builds. 28117 // Unfortunately it makes React unusably slow for some applications. 28118 // To work around this, initialize the fields below with doubles. 28119 // 28120 // Learn more about this here: 28121 // https://github.com/facebook/react/issues/14365 28122 // https://bugs.chromium.org/p/v8/issues/detail?id=8538 28123 this.actualDuration = Number.NaN; 28124 this.actualStartTime = Number.NaN; 28125 this.selfBaseDuration = Number.NaN; 28126 this.treeBaseDuration = Number.NaN; // It's okay to replace the initial doubles with smis after initialization. 28127 // This won't trigger the performance cliff mentioned above, 28128 // and it simplifies other profiler code (including DevTools). 28129 28130 this.actualDuration = 0; 28131 this.actualStartTime = -1; 28132 this.selfBaseDuration = 0; 28133 this.treeBaseDuration = 0; 28134 } 28135 28136 { 28137 // This isn't directly used but is handy for debugging internals: 28138 this._debugSource = null; 28139 this._debugOwner = null; 28140 this._debugNeedsRemount = false; 28141 this._debugHookTypes = null; 28142 28143 if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') { 28144 Object.preventExtensions(this); 28145 } 28146 } 28147 } // This is a constructor function, rather than a POJO constructor, still 28148 // please ensure we do the following: 28149 // 1) Nobody should add any instance methods on this. Instance methods can be 28150 // more difficult to predict when they get optimized and they are almost 28151 // never inlined properly in static compilers. 28152 // 2) Nobody should rely on `instanceof Fiber` for type testing. We should 28153 // always know when it is a fiber. 28154 // 3) We might want to experiment with using numeric keys since they are easier 28155 // to optimize in a non-JIT environment. 28156 // 4) We can easily go from a constructor to a createFiber object literal if that 28157 // is faster. 28158 // 5) It should be easy to port this to a C struct and keep a C implementation 28159 // compatible. 28160 28161 28162 var createFiber = function (tag, pendingProps, key, mode) { 28163 // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors 28164 return new FiberNode(tag, pendingProps, key, mode); 28165 }; 28166 28167 function shouldConstruct$1(Component) { 28168 var prototype = Component.prototype; 28169 return !!(prototype && prototype.isReactComponent); 28170 } 28171 28172 function isSimpleFunctionComponent(type) { 28173 return typeof type === 'function' && !shouldConstruct$1(type) && type.defaultProps === undefined; 28174 } 28175 function resolveLazyComponentTag(Component) { 28176 if (typeof Component === 'function') { 28177 return shouldConstruct$1(Component) ? ClassComponent : FunctionComponent; 28178 } else if (Component !== undefined && Component !== null) { 28179 var $$typeof = Component.$$typeof; 28180 28181 if ($$typeof === REACT_FORWARD_REF_TYPE) { 28182 return ForwardRef; 28183 } 28184 28185 if ($$typeof === REACT_MEMO_TYPE) { 28186 return MemoComponent; 28187 } 28188 } 28189 28190 return IndeterminateComponent; 28191 } // This is used to create an alternate fiber to do work on. 28192 28193 function createWorkInProgress(current, pendingProps) { 28194 var workInProgress = current.alternate; 28195 28196 if (workInProgress === null) { 28197 // We use a double buffering pooling technique because we know that we'll 28198 // only ever need at most two versions of a tree. We pool the "other" unused 28199 // node that we're free to reuse. This is lazily created to avoid allocating 28200 // extra objects for things that are never updated. It also allow us to 28201 // reclaim the extra memory if needed. 28202 workInProgress = createFiber(current.tag, pendingProps, current.key, current.mode); 28203 workInProgress.elementType = current.elementType; 28204 workInProgress.type = current.type; 28205 workInProgress.stateNode = current.stateNode; 28206 28207 { 28208 // DEV-only fields 28209 workInProgress._debugSource = current._debugSource; 28210 workInProgress._debugOwner = current._debugOwner; 28211 workInProgress._debugHookTypes = current._debugHookTypes; 28212 } 28213 28214 workInProgress.alternate = current; 28215 current.alternate = workInProgress; 28216 } else { 28217 workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type. 28218 28219 workInProgress.type = current.type; // We already have an alternate. 28220 // Reset the effect tag. 28221 28222 workInProgress.flags = NoFlags; // The effects are no longer valid. 28223 28224 workInProgress.subtreeFlags = NoFlags; 28225 workInProgress.deletions = null; 28226 28227 { 28228 // We intentionally reset, rather than copy, actualDuration & actualStartTime. 28229 // This prevents time from endlessly accumulating in new commits. 28230 // This has the downside of resetting values for different priority renders, 28231 // But works for yielding (the common case) and should support resuming. 28232 workInProgress.actualDuration = 0; 28233 workInProgress.actualStartTime = -1; 28234 } 28235 } // Reset all effects except static ones. 28236 // Static effects are not specific to a render. 28237 28238 28239 workInProgress.flags = current.flags & StaticMask; 28240 workInProgress.childLanes = current.childLanes; 28241 workInProgress.lanes = current.lanes; 28242 workInProgress.child = current.child; 28243 workInProgress.memoizedProps = current.memoizedProps; 28244 workInProgress.memoizedState = current.memoizedState; 28245 workInProgress.updateQueue = current.updateQueue; // Clone the dependencies object. This is mutated during the render phase, so 28246 // it cannot be shared with the current fiber. 28247 28248 var currentDependencies = current.dependencies; 28249 workInProgress.dependencies = currentDependencies === null ? null : { 28250 lanes: currentDependencies.lanes, 28251 firstContext: currentDependencies.firstContext 28252 }; // These will be overridden during the parent's reconciliation 28253 28254 workInProgress.sibling = current.sibling; 28255 workInProgress.index = current.index; 28256 workInProgress.ref = current.ref; 28257 28258 { 28259 workInProgress.selfBaseDuration = current.selfBaseDuration; 28260 workInProgress.treeBaseDuration = current.treeBaseDuration; 28261 } 28262 28263 { 28264 workInProgress._debugNeedsRemount = current._debugNeedsRemount; 28265 28266 switch (workInProgress.tag) { 28267 case IndeterminateComponent: 28268 case FunctionComponent: 28269 case SimpleMemoComponent: 28270 workInProgress.type = resolveFunctionForHotReloading(current.type); 28271 break; 28272 28273 case ClassComponent: 28274 workInProgress.type = resolveClassForHotReloading(current.type); 28275 break; 28276 28277 case ForwardRef: 28278 workInProgress.type = resolveForwardRefForHotReloading(current.type); 28279 break; 28280 } 28281 } 28282 28283 return workInProgress; 28284 } // Used to reuse a Fiber for a second pass. 28285 28286 function resetWorkInProgress(workInProgress, renderLanes) { 28287 // This resets the Fiber to what createFiber or createWorkInProgress would 28288 // have set the values to before during the first pass. Ideally this wouldn't 28289 // be necessary but unfortunately many code paths reads from the workInProgress 28290 // when they should be reading from current and writing to workInProgress. 28291 // We assume pendingProps, index, key, ref, return are still untouched to 28292 // avoid doing another reconciliation. 28293 // Reset the effect flags but keep any Placement tags, since that's something 28294 // that child fiber is setting, not the reconciliation. 28295 workInProgress.flags &= StaticMask | Placement; // The effects are no longer valid. 28296 28297 var current = workInProgress.alternate; 28298 28299 if (current === null) { 28300 // Reset to createFiber's initial values. 28301 workInProgress.childLanes = NoLanes; 28302 workInProgress.lanes = renderLanes; 28303 workInProgress.child = null; 28304 workInProgress.subtreeFlags = NoFlags; 28305 workInProgress.memoizedProps = null; 28306 workInProgress.memoizedState = null; 28307 workInProgress.updateQueue = null; 28308 workInProgress.dependencies = null; 28309 workInProgress.stateNode = null; 28310 28311 { 28312 // Note: We don't reset the actualTime counts. It's useful to accumulate 28313 // actual time across multiple render passes. 28314 workInProgress.selfBaseDuration = 0; 28315 workInProgress.treeBaseDuration = 0; 28316 } 28317 } else { 28318 // Reset to the cloned values that createWorkInProgress would've. 28319 workInProgress.childLanes = current.childLanes; 28320 workInProgress.lanes = current.lanes; 28321 workInProgress.child = current.child; 28322 workInProgress.subtreeFlags = NoFlags; 28323 workInProgress.deletions = null; 28324 workInProgress.memoizedProps = current.memoizedProps; 28325 workInProgress.memoizedState = current.memoizedState; 28326 workInProgress.updateQueue = current.updateQueue; // Needed because Blocks store data on type. 28327 28328 workInProgress.type = current.type; // Clone the dependencies object. This is mutated during the render phase, so 28329 // it cannot be shared with the current fiber. 28330 28331 var currentDependencies = current.dependencies; 28332 workInProgress.dependencies = currentDependencies === null ? null : { 28333 lanes: currentDependencies.lanes, 28334 firstContext: currentDependencies.firstContext 28335 }; 28336 28337 { 28338 // Note: We don't reset the actualTime counts. It's useful to accumulate 28339 // actual time across multiple render passes. 28340 workInProgress.selfBaseDuration = current.selfBaseDuration; 28341 workInProgress.treeBaseDuration = current.treeBaseDuration; 28342 } 28343 } 28344 28345 return workInProgress; 28346 } 28347 function createHostRootFiber(tag, isStrictMode, concurrentUpdatesByDefaultOverride) { 28348 var mode; 28349 28350 if (tag === ConcurrentRoot) { 28351 mode = ConcurrentMode; 28352 28353 if (isStrictMode === true) { 28354 mode |= StrictLegacyMode; 28355 28356 { 28357 mode |= StrictEffectsMode; 28358 } 28359 } 28360 } else { 28361 mode = NoMode; 28362 } 28363 28364 if ( isDevToolsPresent) { 28365 // Always collect profile timings when DevTools are present. 28366 // This enables DevTools to start capturing timing at any point– 28367 // Without some nodes in the tree having empty base times. 28368 mode |= ProfileMode; 28369 } 28370 28371 return createFiber(HostRoot, null, null, mode); 28372 } 28373 function createFiberFromTypeAndProps(type, // React$ElementType 28374 key, pendingProps, owner, mode, lanes) { 28375 var fiberTag = IndeterminateComponent; // The resolved type is set if we know what the final type will be. I.e. it's not lazy. 28376 28377 var resolvedType = type; 28378 28379 if (typeof type === 'function') { 28380 if (shouldConstruct$1(type)) { 28381 fiberTag = ClassComponent; 28382 28383 { 28384 resolvedType = resolveClassForHotReloading(resolvedType); 28385 } 28386 } else { 28387 { 28388 resolvedType = resolveFunctionForHotReloading(resolvedType); 28389 } 28390 } 28391 } else if (typeof type === 'string') { 28392 fiberTag = HostComponent; 28393 } else { 28394 getTag: switch (type) { 28395 case REACT_FRAGMENT_TYPE: 28396 return createFiberFromFragment(pendingProps.children, mode, lanes, key); 28397 28398 case REACT_STRICT_MODE_TYPE: 28399 fiberTag = Mode; 28400 mode |= StrictLegacyMode; 28401 28402 if ( (mode & ConcurrentMode) !== NoMode) { 28403 // Strict effects should never run on legacy roots 28404 mode |= StrictEffectsMode; 28405 } 28406 28407 break; 28408 28409 case REACT_PROFILER_TYPE: 28410 return createFiberFromProfiler(pendingProps, mode, lanes, key); 28411 28412 case REACT_SUSPENSE_TYPE: 28413 return createFiberFromSuspense(pendingProps, mode, lanes, key); 28414 28415 case REACT_SUSPENSE_LIST_TYPE: 28416 return createFiberFromSuspenseList(pendingProps, mode, lanes, key); 28417 28418 case REACT_OFFSCREEN_TYPE: 28419 return createFiberFromOffscreen(pendingProps, mode, lanes, key); 28420 28421 case REACT_LEGACY_HIDDEN_TYPE: 28422 28423 // eslint-disable-next-line no-fallthrough 28424 28425 case REACT_SCOPE_TYPE: 28426 28427 // eslint-disable-next-line no-fallthrough 28428 28429 case REACT_CACHE_TYPE: 28430 28431 // eslint-disable-next-line no-fallthrough 28432 28433 case REACT_TRACING_MARKER_TYPE: 28434 28435 // eslint-disable-next-line no-fallthrough 28436 28437 case REACT_DEBUG_TRACING_MODE_TYPE: 28438 28439 // eslint-disable-next-line no-fallthrough 28440 28441 default: 28442 { 28443 if (typeof type === 'object' && type !== null) { 28444 switch (type.$$typeof) { 28445 case REACT_PROVIDER_TYPE: 28446 fiberTag = ContextProvider; 28447 break getTag; 28448 28449 case REACT_CONTEXT_TYPE: 28450 // This is a consumer 28451 fiberTag = ContextConsumer; 28452 break getTag; 28453 28454 case REACT_FORWARD_REF_TYPE: 28455 fiberTag = ForwardRef; 28456 28457 { 28458 resolvedType = resolveForwardRefForHotReloading(resolvedType); 28459 } 28460 28461 break getTag; 28462 28463 case REACT_MEMO_TYPE: 28464 fiberTag = MemoComponent; 28465 break getTag; 28466 28467 case REACT_LAZY_TYPE: 28468 fiberTag = LazyComponent; 28469 resolvedType = null; 28470 break getTag; 28471 } 28472 } 28473 28474 var info = ''; 28475 28476 { 28477 if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) { 28478 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.'; 28479 } 28480 28481 var ownerName = owner ? getComponentNameFromFiber(owner) : null; 28482 28483 if (ownerName) { 28484 info += '\n\nCheck the render method of `' + ownerName + '`.'; 28485 } 28486 } 28487 28488 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)); 28489 } 28490 } 28491 } 28492 28493 var fiber = createFiber(fiberTag, pendingProps, key, mode); 28494 fiber.elementType = type; 28495 fiber.type = resolvedType; 28496 fiber.lanes = lanes; 28497 28498 { 28499 fiber._debugOwner = owner; 28500 } 28501 28502 return fiber; 28503 } 28504 function createFiberFromElement(element, mode, lanes) { 28505 var owner = null; 28506 28507 { 28508 owner = element._owner; 28509 } 28510 28511 var type = element.type; 28512 var key = element.key; 28513 var pendingProps = element.props; 28514 var fiber = createFiberFromTypeAndProps(type, key, pendingProps, owner, mode, lanes); 28515 28516 { 28517 fiber._debugSource = element._source; 28518 fiber._debugOwner = element._owner; 28519 } 28520 28521 return fiber; 28522 } 28523 function createFiberFromFragment(elements, mode, lanes, key) { 28524 var fiber = createFiber(Fragment, elements, key, mode); 28525 fiber.lanes = lanes; 28526 return fiber; 28527 } 28528 28529 function createFiberFromProfiler(pendingProps, mode, lanes, key) { 28530 { 28531 if (typeof pendingProps.id !== 'string') { 28532 error('Profiler must specify an "id" of type `string` as a prop. Received the type `%s` instead.', typeof pendingProps.id); 28533 } 28534 } 28535 28536 var fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode); 28537 fiber.elementType = REACT_PROFILER_TYPE; 28538 fiber.lanes = lanes; 28539 28540 { 28541 fiber.stateNode = { 28542 effectDuration: 0, 28543 passiveEffectDuration: 0 28544 }; 28545 } 28546 28547 return fiber; 28548 } 28549 28550 function createFiberFromSuspense(pendingProps, mode, lanes, key) { 28551 var fiber = createFiber(SuspenseComponent, pendingProps, key, mode); 28552 fiber.elementType = REACT_SUSPENSE_TYPE; 28553 fiber.lanes = lanes; 28554 return fiber; 28555 } 28556 function createFiberFromSuspenseList(pendingProps, mode, lanes, key) { 28557 var fiber = createFiber(SuspenseListComponent, pendingProps, key, mode); 28558 fiber.elementType = REACT_SUSPENSE_LIST_TYPE; 28559 fiber.lanes = lanes; 28560 return fiber; 28561 } 28562 function createFiberFromOffscreen(pendingProps, mode, lanes, key) { 28563 var fiber = createFiber(OffscreenComponent, pendingProps, key, mode); 28564 fiber.elementType = REACT_OFFSCREEN_TYPE; 28565 fiber.lanes = lanes; 28566 var primaryChildInstance = { 28567 isHidden: false 28568 }; 28569 fiber.stateNode = primaryChildInstance; 28570 return fiber; 28571 } 28572 function createFiberFromText(content, mode, lanes) { 28573 var fiber = createFiber(HostText, content, null, mode); 28574 fiber.lanes = lanes; 28575 return fiber; 28576 } 28577 function createFiberFromHostInstanceForDeletion() { 28578 var fiber = createFiber(HostComponent, null, null, NoMode); 28579 fiber.elementType = 'DELETED'; 28580 return fiber; 28581 } 28582 function createFiberFromDehydratedFragment(dehydratedNode) { 28583 var fiber = createFiber(DehydratedFragment, null, null, NoMode); 28584 fiber.stateNode = dehydratedNode; 28585 return fiber; 28586 } 28587 function createFiberFromPortal(portal, mode, lanes) { 28588 var pendingProps = portal.children !== null ? portal.children : []; 28589 var fiber = createFiber(HostPortal, pendingProps, portal.key, mode); 28590 fiber.lanes = lanes; 28591 fiber.stateNode = { 28592 containerInfo: portal.containerInfo, 28593 pendingChildren: null, 28594 // Used by persistent updates 28595 implementation: portal.implementation 28596 }; 28597 return fiber; 28598 } // Used for stashing WIP properties to replay failed work in DEV. 28599 28600 function assignFiberPropertiesInDEV(target, source) { 28601 if (target === null) { 28602 // This Fiber's initial properties will always be overwritten. 28603 // We only use a Fiber to ensure the same hidden class so DEV isn't slow. 28604 target = createFiber(IndeterminateComponent, null, null, NoMode); 28605 } // This is intentionally written as a list of all properties. 28606 // We tried to use Object.assign() instead but this is called in 28607 // the hottest path, and Object.assign() was too slow: 28608 // https://github.com/facebook/react/issues/12502 28609 // This code is DEV-only so size is not a concern. 28610 28611 28612 target.tag = source.tag; 28613 target.key = source.key; 28614 target.elementType = source.elementType; 28615 target.type = source.type; 28616 target.stateNode = source.stateNode; 28617 target.return = source.return; 28618 target.child = source.child; 28619 target.sibling = source.sibling; 28620 target.index = source.index; 28621 target.ref = source.ref; 28622 target.pendingProps = source.pendingProps; 28623 target.memoizedProps = source.memoizedProps; 28624 target.updateQueue = source.updateQueue; 28625 target.memoizedState = source.memoizedState; 28626 target.dependencies = source.dependencies; 28627 target.mode = source.mode; 28628 target.flags = source.flags; 28629 target.subtreeFlags = source.subtreeFlags; 28630 target.deletions = source.deletions; 28631 target.lanes = source.lanes; 28632 target.childLanes = source.childLanes; 28633 target.alternate = source.alternate; 28634 28635 { 28636 target.actualDuration = source.actualDuration; 28637 target.actualStartTime = source.actualStartTime; 28638 target.selfBaseDuration = source.selfBaseDuration; 28639 target.treeBaseDuration = source.treeBaseDuration; 28640 } 28641 28642 target._debugSource = source._debugSource; 28643 target._debugOwner = source._debugOwner; 28644 target._debugNeedsRemount = source._debugNeedsRemount; 28645 target._debugHookTypes = source._debugHookTypes; 28646 return target; 28647 } 28648 28649 function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix, onRecoverableError) { 28650 this.tag = tag; 28651 this.containerInfo = containerInfo; 28652 this.pendingChildren = null; 28653 this.current = null; 28654 this.pingCache = null; 28655 this.finishedWork = null; 28656 this.timeoutHandle = noTimeout; 28657 this.context = null; 28658 this.pendingContext = null; 28659 this.callbackNode = null; 28660 this.callbackPriority = NoLane; 28661 this.eventTimes = createLaneMap(NoLanes); 28662 this.expirationTimes = createLaneMap(NoTimestamp); 28663 this.pendingLanes = NoLanes; 28664 this.suspendedLanes = NoLanes; 28665 this.pingedLanes = NoLanes; 28666 this.expiredLanes = NoLanes; 28667 this.mutableReadLanes = NoLanes; 28668 this.finishedLanes = NoLanes; 28669 this.entangledLanes = NoLanes; 28670 this.entanglements = createLaneMap(NoLanes); 28671 this.identifierPrefix = identifierPrefix; 28672 this.onRecoverableError = onRecoverableError; 28673 28674 { 28675 this.mutableSourceEagerHydrationData = null; 28676 } 28677 28678 { 28679 this.effectDuration = 0; 28680 this.passiveEffectDuration = 0; 28681 } 28682 28683 { 28684 this.memoizedUpdaters = new Set(); 28685 var pendingUpdatersLaneMap = this.pendingUpdatersLaneMap = []; 28686 28687 for (var _i = 0; _i < TotalLanes; _i++) { 28688 pendingUpdatersLaneMap.push(new Set()); 28689 } 28690 } 28691 28692 { 28693 switch (tag) { 28694 case ConcurrentRoot: 28695 this._debugRootType = hydrate ? 'hydrateRoot()' : 'createRoot()'; 28696 break; 28697 28698 case LegacyRoot: 28699 this._debugRootType = hydrate ? 'hydrate()' : 'render()'; 28700 break; 28701 } 28702 } 28703 } 28704 28705 function createFiberRoot(containerInfo, tag, hydrate, initialChildren, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, // TODO: We have several of these arguments that are conceptually part of the 28706 // host config, but because they are passed in at runtime, we have to thread 28707 // them through the root constructor. Perhaps we should put them all into a 28708 // single type, like a DynamicHostConfig that is defined by the renderer. 28709 identifierPrefix, onRecoverableError, transitionCallbacks) { 28710 var root = new FiberRootNode(containerInfo, tag, hydrate, identifierPrefix, onRecoverableError); 28711 // stateNode is any. 28712 28713 28714 var uninitializedFiber = createHostRootFiber(tag, isStrictMode); 28715 root.current = uninitializedFiber; 28716 uninitializedFiber.stateNode = root; 28717 28718 { 28719 var _initialState = { 28720 element: initialChildren, 28721 isDehydrated: hydrate, 28722 cache: null, 28723 // not enabled yet 28724 transitions: null, 28725 pendingSuspenseBoundaries: null 28726 }; 28727 uninitializedFiber.memoizedState = _initialState; 28728 } 28729 28730 initializeUpdateQueue(uninitializedFiber); 28731 return root; 28732 } 28733 28734 var ReactVersion = '18.3.1'; 28735 28736 function createPortal(children, containerInfo, // TODO: figure out the API for cross-renderer implementation. 28737 implementation) { 28738 var key = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; 28739 28740 { 28741 checkKeyStringCoercion(key); 28742 } 28743 28744 return { 28745 // This tag allow us to uniquely identify this as a React Portal 28746 $$typeof: REACT_PORTAL_TYPE, 28747 key: key == null ? null : '' + key, 28748 children: children, 28749 containerInfo: containerInfo, 28750 implementation: implementation 28751 }; 28752 } 28753 28754 var didWarnAboutNestedUpdates; 28755 var didWarnAboutFindNodeInStrictMode; 28756 28757 { 28758 didWarnAboutNestedUpdates = false; 28759 didWarnAboutFindNodeInStrictMode = {}; 28760 } 28761 28762 function getContextForSubtree(parentComponent) { 28763 if (!parentComponent) { 28764 return emptyContextObject; 28765 } 28766 28767 var fiber = get(parentComponent); 28768 var parentContext = findCurrentUnmaskedContext(fiber); 28769 28770 if (fiber.tag === ClassComponent) { 28771 var Component = fiber.type; 28772 28773 if (isContextProvider(Component)) { 28774 return processChildContext(fiber, Component, parentContext); 28775 } 28776 } 28777 28778 return parentContext; 28779 } 28780 28781 function findHostInstanceWithWarning(component, methodName) { 28782 { 28783 var fiber = get(component); 28784 28785 if (fiber === undefined) { 28786 if (typeof component.render === 'function') { 28787 throw new Error('Unable to find node on an unmounted component.'); 28788 } else { 28789 var keys = Object.keys(component).join(','); 28790 throw new Error("Argument appears to not be a ReactComponent. Keys: " + keys); 28791 } 28792 } 28793 28794 var hostFiber = findCurrentHostFiber(fiber); 28795 28796 if (hostFiber === null) { 28797 return null; 28798 } 28799 28800 if (hostFiber.mode & StrictLegacyMode) { 28801 var componentName = getComponentNameFromFiber(fiber) || 'Component'; 28802 28803 if (!didWarnAboutFindNodeInStrictMode[componentName]) { 28804 didWarnAboutFindNodeInStrictMode[componentName] = true; 28805 var previousFiber = current; 28806 28807 try { 28808 setCurrentFiber(hostFiber); 28809 28810 if (fiber.mode & StrictLegacyMode) { 28811 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); 28812 } else { 28813 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); 28814 } 28815 } finally { 28816 // Ideally this should reset to previous but this shouldn't be called in 28817 // render and there's another warning for that anyway. 28818 if (previousFiber) { 28819 setCurrentFiber(previousFiber); 28820 } else { 28821 resetCurrentFiber(); 28822 } 28823 } 28824 } 28825 } 28826 28827 return hostFiber.stateNode; 28828 } 28829 } 28830 28831 function createContainer(containerInfo, tag, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError, transitionCallbacks) { 28832 var hydrate = false; 28833 var initialChildren = null; 28834 return createFiberRoot(containerInfo, tag, hydrate, initialChildren, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError); 28835 } 28836 function createHydrationContainer(initialChildren, // TODO: Remove `callback` when we delete legacy mode. 28837 callback, containerInfo, tag, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError, transitionCallbacks) { 28838 var hydrate = true; 28839 var root = createFiberRoot(containerInfo, tag, hydrate, initialChildren, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError); // TODO: Move this to FiberRoot constructor 28840 28841 root.context = getContextForSubtree(null); // Schedule the initial render. In a hydration root, this is different from 28842 // a regular update because the initial render must match was was rendered 28843 // on the server. 28844 // NOTE: This update intentionally doesn't have a payload. We're only using 28845 // the update to schedule work on the root fiber (and, for legacy roots, to 28846 // enqueue the callback if one is provided). 28847 28848 var current = root.current; 28849 var eventTime = requestEventTime(); 28850 var lane = requestUpdateLane(current); 28851 var update = createUpdate(eventTime, lane); 28852 update.callback = callback !== undefined && callback !== null ? callback : null; 28853 enqueueUpdate(current, update, lane); 28854 scheduleInitialHydrationOnRoot(root, lane, eventTime); 28855 return root; 28856 } 28857 function updateContainer(element, container, parentComponent, callback) { 28858 { 28859 onScheduleRoot(container, element); 28860 } 28861 28862 var current$1 = container.current; 28863 var eventTime = requestEventTime(); 28864 var lane = requestUpdateLane(current$1); 28865 28866 { 28867 markRenderScheduled(lane); 28868 } 28869 28870 var context = getContextForSubtree(parentComponent); 28871 28872 if (container.context === null) { 28873 container.context = context; 28874 } else { 28875 container.pendingContext = context; 28876 } 28877 28878 { 28879 if (isRendering && current !== null && !didWarnAboutNestedUpdates) { 28880 didWarnAboutNestedUpdates = true; 28881 28882 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'); 28883 } 28884 } 28885 28886 var update = createUpdate(eventTime, lane); // Caution: React DevTools currently depends on this property 28887 // being called "element". 28888 28889 update.payload = { 28890 element: element 28891 }; 28892 callback = callback === undefined ? null : callback; 28893 28894 if (callback !== null) { 28895 { 28896 if (typeof callback !== 'function') { 28897 error('render(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callback); 28898 } 28899 } 28900 28901 update.callback = callback; 28902 } 28903 28904 var root = enqueueUpdate(current$1, update, lane); 28905 28906 if (root !== null) { 28907 scheduleUpdateOnFiber(root, current$1, lane, eventTime); 28908 entangleTransitions(root, current$1, lane); 28909 } 28910 28911 return lane; 28912 } 28913 function getPublicRootInstance(container) { 28914 var containerFiber = container.current; 28915 28916 if (!containerFiber.child) { 28917 return null; 28918 } 28919 28920 switch (containerFiber.child.tag) { 28921 case HostComponent: 28922 return getPublicInstance(containerFiber.child.stateNode); 28923 28924 default: 28925 return containerFiber.child.stateNode; 28926 } 28927 } 28928 function attemptSynchronousHydration$1(fiber) { 28929 switch (fiber.tag) { 28930 case HostRoot: 28931 { 28932 var root = fiber.stateNode; 28933 28934 if (isRootDehydrated(root)) { 28935 // Flush the first scheduled "update". 28936 var lanes = getHighestPriorityPendingLanes(root); 28937 flushRoot(root, lanes); 28938 } 28939 28940 break; 28941 } 28942 28943 case SuspenseComponent: 28944 { 28945 flushSync(function () { 28946 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 28947 28948 if (root !== null) { 28949 var eventTime = requestEventTime(); 28950 scheduleUpdateOnFiber(root, fiber, SyncLane, eventTime); 28951 } 28952 }); // If we're still blocked after this, we need to increase 28953 // the priority of any promises resolving within this 28954 // boundary so that they next attempt also has higher pri. 28955 28956 var retryLane = SyncLane; 28957 markRetryLaneIfNotHydrated(fiber, retryLane); 28958 break; 28959 } 28960 } 28961 } 28962 28963 function markRetryLaneImpl(fiber, retryLane) { 28964 var suspenseState = fiber.memoizedState; 28965 28966 if (suspenseState !== null && suspenseState.dehydrated !== null) { 28967 suspenseState.retryLane = higherPriorityLane(suspenseState.retryLane, retryLane); 28968 } 28969 } // Increases the priority of thenables when they resolve within this boundary. 28970 28971 28972 function markRetryLaneIfNotHydrated(fiber, retryLane) { 28973 markRetryLaneImpl(fiber, retryLane); 28974 var alternate = fiber.alternate; 28975 28976 if (alternate) { 28977 markRetryLaneImpl(alternate, retryLane); 28978 } 28979 } 28980 function attemptContinuousHydration$1(fiber) { 28981 if (fiber.tag !== SuspenseComponent) { 28982 // We ignore HostRoots here because we can't increase 28983 // their priority and they should not suspend on I/O, 28984 // since you have to wrap anything that might suspend in 28985 // Suspense. 28986 return; 28987 } 28988 28989 var lane = SelectiveHydrationLane; 28990 var root = enqueueConcurrentRenderForLane(fiber, lane); 28991 28992 if (root !== null) { 28993 var eventTime = requestEventTime(); 28994 scheduleUpdateOnFiber(root, fiber, lane, eventTime); 28995 } 28996 28997 markRetryLaneIfNotHydrated(fiber, lane); 28998 } 28999 function attemptHydrationAtCurrentPriority$1(fiber) { 29000 if (fiber.tag !== SuspenseComponent) { 29001 // We ignore HostRoots here because we can't increase 29002 // their priority other than synchronously flush it. 29003 return; 29004 } 29005 29006 var lane = requestUpdateLane(fiber); 29007 var root = enqueueConcurrentRenderForLane(fiber, lane); 29008 29009 if (root !== null) { 29010 var eventTime = requestEventTime(); 29011 scheduleUpdateOnFiber(root, fiber, lane, eventTime); 29012 } 29013 29014 markRetryLaneIfNotHydrated(fiber, lane); 29015 } 29016 function findHostInstanceWithNoPortals(fiber) { 29017 var hostFiber = findCurrentHostFiberWithNoPortals(fiber); 29018 29019 if (hostFiber === null) { 29020 return null; 29021 } 29022 29023 return hostFiber.stateNode; 29024 } 29025 29026 var shouldErrorImpl = function (fiber) { 29027 return null; 29028 }; 29029 29030 function shouldError(fiber) { 29031 return shouldErrorImpl(fiber); 29032 } 29033 29034 var shouldSuspendImpl = function (fiber) { 29035 return false; 29036 }; 29037 29038 function shouldSuspend(fiber) { 29039 return shouldSuspendImpl(fiber); 29040 } 29041 var overrideHookState = null; 29042 var overrideHookStateDeletePath = null; 29043 var overrideHookStateRenamePath = null; 29044 var overrideProps = null; 29045 var overridePropsDeletePath = null; 29046 var overridePropsRenamePath = null; 29047 var scheduleUpdate = null; 29048 var setErrorHandler = null; 29049 var setSuspenseHandler = null; 29050 29051 { 29052 var copyWithDeleteImpl = function (obj, path, index) { 29053 var key = path[index]; 29054 var updated = isArray(obj) ? obj.slice() : assign({}, obj); 29055 29056 if (index + 1 === path.length) { 29057 if (isArray(updated)) { 29058 updated.splice(key, 1); 29059 } else { 29060 delete updated[key]; 29061 } 29062 29063 return updated; 29064 } // $FlowFixMe number or string is fine here 29065 29066 29067 updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); 29068 return updated; 29069 }; 29070 29071 var copyWithDelete = function (obj, path) { 29072 return copyWithDeleteImpl(obj, path, 0); 29073 }; 29074 29075 var copyWithRenameImpl = function (obj, oldPath, newPath, index) { 29076 var oldKey = oldPath[index]; 29077 var updated = isArray(obj) ? obj.slice() : assign({}, obj); 29078 29079 if (index + 1 === oldPath.length) { 29080 var newKey = newPath[index]; // $FlowFixMe number or string is fine here 29081 29082 updated[newKey] = updated[oldKey]; 29083 29084 if (isArray(updated)) { 29085 updated.splice(oldKey, 1); 29086 } else { 29087 delete updated[oldKey]; 29088 } 29089 } else { 29090 // $FlowFixMe number or string is fine here 29091 updated[oldKey] = copyWithRenameImpl( // $FlowFixMe number or string is fine here 29092 obj[oldKey], oldPath, newPath, index + 1); 29093 } 29094 29095 return updated; 29096 }; 29097 29098 var copyWithRename = function (obj, oldPath, newPath) { 29099 if (oldPath.length !== newPath.length) { 29100 warn('copyWithRename() expects paths of the same length'); 29101 29102 return; 29103 } else { 29104 for (var i = 0; i < newPath.length - 1; i++) { 29105 if (oldPath[i] !== newPath[i]) { 29106 warn('copyWithRename() expects paths to be the same except for the deepest key'); 29107 29108 return; 29109 } 29110 } 29111 } 29112 29113 return copyWithRenameImpl(obj, oldPath, newPath, 0); 29114 }; 29115 29116 var copyWithSetImpl = function (obj, path, index, value) { 29117 if (index >= path.length) { 29118 return value; 29119 } 29120 29121 var key = path[index]; 29122 var updated = isArray(obj) ? obj.slice() : assign({}, obj); // $FlowFixMe number or string is fine here 29123 29124 updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); 29125 return updated; 29126 }; 29127 29128 var copyWithSet = function (obj, path, value) { 29129 return copyWithSetImpl(obj, path, 0, value); 29130 }; 29131 29132 var findHook = function (fiber, id) { 29133 // For now, the "id" of stateful hooks is just the stateful hook index. 29134 // This may change in the future with e.g. nested hooks. 29135 var currentHook = fiber.memoizedState; 29136 29137 while (currentHook !== null && id > 0) { 29138 currentHook = currentHook.next; 29139 id--; 29140 } 29141 29142 return currentHook; 29143 }; // Support DevTools editable values for useState and useReducer. 29144 29145 29146 overrideHookState = function (fiber, id, path, value) { 29147 var hook = findHook(fiber, id); 29148 29149 if (hook !== null) { 29150 var newState = copyWithSet(hook.memoizedState, path, value); 29151 hook.memoizedState = newState; 29152 hook.baseState = newState; // We aren't actually adding an update to the queue, 29153 // because there is no update we can add for useReducer hooks that won't trigger an error. 29154 // (There's no appropriate action type for DevTools overrides.) 29155 // As a result though, React will see the scheduled update as a noop and bailout. 29156 // Shallow cloning props works as a workaround for now to bypass the bailout check. 29157 29158 fiber.memoizedProps = assign({}, fiber.memoizedProps); 29159 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 29160 29161 if (root !== null) { 29162 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 29163 } 29164 } 29165 }; 29166 29167 overrideHookStateDeletePath = function (fiber, id, path) { 29168 var hook = findHook(fiber, id); 29169 29170 if (hook !== null) { 29171 var newState = copyWithDelete(hook.memoizedState, path); 29172 hook.memoizedState = newState; 29173 hook.baseState = newState; // We aren't actually adding an update to the queue, 29174 // because there is no update we can add for useReducer hooks that won't trigger an error. 29175 // (There's no appropriate action type for DevTools overrides.) 29176 // As a result though, React will see the scheduled update as a noop and bailout. 29177 // Shallow cloning props works as a workaround for now to bypass the bailout check. 29178 29179 fiber.memoizedProps = assign({}, fiber.memoizedProps); 29180 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 29181 29182 if (root !== null) { 29183 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 29184 } 29185 } 29186 }; 29187 29188 overrideHookStateRenamePath = function (fiber, id, oldPath, newPath) { 29189 var hook = findHook(fiber, id); 29190 29191 if (hook !== null) { 29192 var newState = copyWithRename(hook.memoizedState, oldPath, newPath); 29193 hook.memoizedState = newState; 29194 hook.baseState = newState; // We aren't actually adding an update to the queue, 29195 // because there is no update we can add for useReducer hooks that won't trigger an error. 29196 // (There's no appropriate action type for DevTools overrides.) 29197 // As a result though, React will see the scheduled update as a noop and bailout. 29198 // Shallow cloning props works as a workaround for now to bypass the bailout check. 29199 29200 fiber.memoizedProps = assign({}, fiber.memoizedProps); 29201 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 29202 29203 if (root !== null) { 29204 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 29205 } 29206 } 29207 }; // Support DevTools props for function components, forwardRef, memo, host components, etc. 29208 29209 29210 overrideProps = function (fiber, path, value) { 29211 fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value); 29212 29213 if (fiber.alternate) { 29214 fiber.alternate.pendingProps = fiber.pendingProps; 29215 } 29216 29217 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 29218 29219 if (root !== null) { 29220 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 29221 } 29222 }; 29223 29224 overridePropsDeletePath = function (fiber, path) { 29225 fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path); 29226 29227 if (fiber.alternate) { 29228 fiber.alternate.pendingProps = fiber.pendingProps; 29229 } 29230 29231 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 29232 29233 if (root !== null) { 29234 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 29235 } 29236 }; 29237 29238 overridePropsRenamePath = function (fiber, oldPath, newPath) { 29239 fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath); 29240 29241 if (fiber.alternate) { 29242 fiber.alternate.pendingProps = fiber.pendingProps; 29243 } 29244 29245 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 29246 29247 if (root !== null) { 29248 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 29249 } 29250 }; 29251 29252 scheduleUpdate = function (fiber) { 29253 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 29254 29255 if (root !== null) { 29256 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 29257 } 29258 }; 29259 29260 setErrorHandler = function (newShouldErrorImpl) { 29261 shouldErrorImpl = newShouldErrorImpl; 29262 }; 29263 29264 setSuspenseHandler = function (newShouldSuspendImpl) { 29265 shouldSuspendImpl = newShouldSuspendImpl; 29266 }; 29267 } 29268 29269 function findHostInstanceByFiber(fiber) { 29270 var hostFiber = findCurrentHostFiber(fiber); 29271 29272 if (hostFiber === null) { 29273 return null; 29274 } 29275 29276 return hostFiber.stateNode; 29277 } 29278 29279 function emptyFindFiberByHostInstance(instance) { 29280 return null; 29281 } 29282 29283 function getCurrentFiberForDevTools() { 29284 return current; 29285 } 29286 29287 function injectIntoDevTools(devToolsConfig) { 29288 var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance; 29289 var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; 29290 return injectInternals({ 29291 bundleType: devToolsConfig.bundleType, 29292 version: devToolsConfig.version, 29293 rendererPackageName: devToolsConfig.rendererPackageName, 29294 rendererConfig: devToolsConfig.rendererConfig, 29295 overrideHookState: overrideHookState, 29296 overrideHookStateDeletePath: overrideHookStateDeletePath, 29297 overrideHookStateRenamePath: overrideHookStateRenamePath, 29298 overrideProps: overrideProps, 29299 overridePropsDeletePath: overridePropsDeletePath, 29300 overridePropsRenamePath: overridePropsRenamePath, 29301 setErrorHandler: setErrorHandler, 29302 setSuspenseHandler: setSuspenseHandler, 29303 scheduleUpdate: scheduleUpdate, 29304 currentDispatcherRef: ReactCurrentDispatcher, 29305 findHostInstanceByFiber: findHostInstanceByFiber, 29306 findFiberByHostInstance: findFiberByHostInstance || emptyFindFiberByHostInstance, 29307 // React Refresh 29308 findHostInstancesForRefresh: findHostInstancesForRefresh , 29309 scheduleRefresh: scheduleRefresh , 29310 scheduleRoot: scheduleRoot , 29311 setRefreshHandler: setRefreshHandler , 29312 // Enables DevTools to append owner stacks to error messages in DEV mode. 29313 getCurrentFiber: getCurrentFiberForDevTools , 29314 // Enables DevTools to detect reconciler version rather than renderer version 29315 // which may not match for third party renderers. 29316 reconcilerVersion: ReactVersion 29317 }); 29318 } 29319 29320 /* global reportError */ 29321 29322 var defaultOnRecoverableError = typeof reportError === 'function' ? // In modern browsers, reportError will dispatch an error event, 29323 // emulating an uncaught JavaScript error. 29324 reportError : function (error) { 29325 // In older browsers and test environments, fallback to console.error. 29326 // eslint-disable-next-line react-internal/no-production-logging 29327 console['error'](error); 29328 }; 29329 29330 function ReactDOMRoot(internalRoot) { 29331 this._internalRoot = internalRoot; 29332 } 29333 29334 ReactDOMHydrationRoot.prototype.render = ReactDOMRoot.prototype.render = function (children) { 29335 var root = this._internalRoot; 29336 29337 if (root === null) { 29338 throw new Error('Cannot update an unmounted root.'); 29339 } 29340 29341 { 29342 if (typeof arguments[1] === 'function') { 29343 error('render(...): does not support the second callback argument. ' + 'To execute a side effect after rendering, declare it in a component body with useEffect().'); 29344 } else if (isValidContainer(arguments[1])) { 29345 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."); 29346 } else if (typeof arguments[1] !== 'undefined') { 29347 error('You passed a second argument to root.render(...) but it only accepts ' + 'one argument.'); 29348 } 29349 29350 var container = root.containerInfo; 29351 29352 if (container.nodeType !== COMMENT_NODE) { 29353 var hostInstance = findHostInstanceWithNoPortals(root.current); 29354 29355 if (hostInstance) { 29356 if (hostInstance.parentNode !== container) { 29357 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."); 29358 } 29359 } 29360 } 29361 } 29362 29363 updateContainer(children, root, null, null); 29364 }; 29365 29366 ReactDOMHydrationRoot.prototype.unmount = ReactDOMRoot.prototype.unmount = function () { 29367 { 29368 if (typeof arguments[0] === 'function') { 29369 error('unmount(...): does not support a callback argument. ' + 'To execute a side effect after rendering, declare it in a component body with useEffect().'); 29370 } 29371 } 29372 29373 var root = this._internalRoot; 29374 29375 if (root !== null) { 29376 this._internalRoot = null; 29377 var container = root.containerInfo; 29378 29379 { 29380 if (isAlreadyRendering()) { 29381 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.'); 29382 } 29383 } 29384 29385 flushSync(function () { 29386 updateContainer(null, root, null, null); 29387 }); 29388 unmarkContainerAsRoot(container); 29389 } 29390 }; 29391 29392 function createRoot(container, options) { 29393 if (!isValidContainer(container)) { 29394 throw new Error('createRoot(...): Target container is not a DOM element.'); 29395 } 29396 29397 warnIfReactDOMContainerInDEV(container); 29398 var isStrictMode = false; 29399 var concurrentUpdatesByDefaultOverride = false; 29400 var identifierPrefix = ''; 29401 var onRecoverableError = defaultOnRecoverableError; 29402 var transitionCallbacks = null; 29403 29404 if (options !== null && options !== undefined) { 29405 { 29406 if (options.hydrate) { 29407 warn('hydrate through createRoot is deprecated. Use ReactDOMClient.hydrateRoot(container, <App />) instead.'); 29408 } else { 29409 if (typeof options === 'object' && options !== null && options.$$typeof === REACT_ELEMENT_TYPE) { 29410 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 />);'); 29411 } 29412 } 29413 } 29414 29415 if (options.unstable_strictMode === true) { 29416 isStrictMode = true; 29417 } 29418 29419 if (options.identifierPrefix !== undefined) { 29420 identifierPrefix = options.identifierPrefix; 29421 } 29422 29423 if (options.onRecoverableError !== undefined) { 29424 onRecoverableError = options.onRecoverableError; 29425 } 29426 29427 if (options.transitionCallbacks !== undefined) { 29428 transitionCallbacks = options.transitionCallbacks; 29429 } 29430 } 29431 29432 var root = createContainer(container, ConcurrentRoot, null, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError); 29433 markContainerAsRoot(root.current, container); 29434 var rootContainerElement = container.nodeType === COMMENT_NODE ? container.parentNode : container; 29435 listenToAllSupportedEvents(rootContainerElement); 29436 return new ReactDOMRoot(root); 29437 } 29438 29439 function ReactDOMHydrationRoot(internalRoot) { 29440 this._internalRoot = internalRoot; 29441 } 29442 29443 function scheduleHydration(target) { 29444 if (target) { 29445 queueExplicitHydrationTarget(target); 29446 } 29447 } 29448 29449 ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = scheduleHydration; 29450 function hydrateRoot(container, initialChildren, options) { 29451 if (!isValidContainer(container)) { 29452 throw new Error('hydrateRoot(...): Target container is not a DOM element.'); 29453 } 29454 29455 warnIfReactDOMContainerInDEV(container); 29456 29457 { 29458 if (initialChildren === undefined) { 29459 error('Must provide initial children as second argument to hydrateRoot. ' + 'Example usage: hydrateRoot(domContainer, <App />)'); 29460 } 29461 } // For now we reuse the whole bag of options since they contain 29462 // the hydration callbacks. 29463 29464 29465 var hydrationCallbacks = options != null ? options : null; // TODO: Delete this option 29466 29467 var mutableSources = options != null && options.hydratedSources || null; 29468 var isStrictMode = false; 29469 var concurrentUpdatesByDefaultOverride = false; 29470 var identifierPrefix = ''; 29471 var onRecoverableError = defaultOnRecoverableError; 29472 29473 if (options !== null && options !== undefined) { 29474 if (options.unstable_strictMode === true) { 29475 isStrictMode = true; 29476 } 29477 29478 if (options.identifierPrefix !== undefined) { 29479 identifierPrefix = options.identifierPrefix; 29480 } 29481 29482 if (options.onRecoverableError !== undefined) { 29483 onRecoverableError = options.onRecoverableError; 29484 } 29485 } 29486 29487 var root = createHydrationContainer(initialChildren, null, container, ConcurrentRoot, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError); 29488 markContainerAsRoot(root.current, container); // This can't be a comment node since hydration doesn't work on comment nodes anyway. 29489 29490 listenToAllSupportedEvents(container); 29491 29492 if (mutableSources) { 29493 for (var i = 0; i < mutableSources.length; i++) { 29494 var mutableSource = mutableSources[i]; 29495 registerMutableSourceForHydration(root, mutableSource); 29496 } 29497 } 29498 29499 return new ReactDOMHydrationRoot(root); 29500 } 29501 function isValidContainer(node) { 29502 return !!(node && (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE || !disableCommentsAsDOMContainers )); 29503 } // TODO: Remove this function which also includes comment nodes. 29504 // We only use it in places that are currently more relaxed. 29505 29506 function isValidContainerLegacy(node) { 29507 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 ')); 29508 } 29509 29510 function warnIfReactDOMContainerInDEV(container) { 29511 { 29512 if (container.nodeType === ELEMENT_NODE && container.tagName && container.tagName.toUpperCase() === 'BODY') { 29513 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.'); 29514 } 29515 29516 if (isContainerMarkedAsRoot(container)) { 29517 if (container._reactRootContainer) { 29518 error('You are calling ReactDOMClient.createRoot() on a container that was previously ' + 'passed to ReactDOM.render(). This is not supported.'); 29519 } else { 29520 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.'); 29521 } 29522 } 29523 } 29524 } 29525 29526 var ReactCurrentOwner$3 = ReactSharedInternals.ReactCurrentOwner; 29527 var topLevelUpdateWarnings; 29528 29529 { 29530 topLevelUpdateWarnings = function (container) { 29531 if (container._reactRootContainer && container.nodeType !== COMMENT_NODE) { 29532 var hostInstance = findHostInstanceWithNoPortals(container._reactRootContainer.current); 29533 29534 if (hostInstance) { 29535 if (hostInstance.parentNode !== container) { 29536 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.'); 29537 } 29538 } 29539 } 29540 29541 var isRootRenderedBySomeReact = !!container._reactRootContainer; 29542 var rootEl = getReactRootElementInContainer(container); 29543 var hasNonRootReactChild = !!(rootEl && getInstanceFromNode(rootEl)); 29544 29545 if (hasNonRootReactChild && !isRootRenderedBySomeReact) { 29546 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.'); 29547 } 29548 29549 if (container.nodeType === ELEMENT_NODE && container.tagName && container.tagName.toUpperCase() === 'BODY') { 29550 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.'); 29551 } 29552 }; 29553 } 29554 29555 function getReactRootElementInContainer(container) { 29556 if (!container) { 29557 return null; 29558 } 29559 29560 if (container.nodeType === DOCUMENT_NODE) { 29561 return container.documentElement; 29562 } else { 29563 return container.firstChild; 29564 } 29565 } 29566 29567 function noopOnRecoverableError() {// This isn't reachable because onRecoverableError isn't called in the 29568 // legacy API. 29569 } 29570 29571 function legacyCreateRootFromDOMContainer(container, initialChildren, parentComponent, callback, isHydrationContainer) { 29572 if (isHydrationContainer) { 29573 if (typeof callback === 'function') { 29574 var originalCallback = callback; 29575 29576 callback = function () { 29577 var instance = getPublicRootInstance(root); 29578 originalCallback.call(instance); 29579 }; 29580 } 29581 29582 var root = createHydrationContainer(initialChildren, callback, container, LegacyRoot, null, // hydrationCallbacks 29583 false, // isStrictMode 29584 false, // concurrentUpdatesByDefaultOverride, 29585 '', // identifierPrefix 29586 noopOnRecoverableError); 29587 container._reactRootContainer = root; 29588 markContainerAsRoot(root.current, container); 29589 var rootContainerElement = container.nodeType === COMMENT_NODE ? container.parentNode : container; 29590 listenToAllSupportedEvents(rootContainerElement); 29591 flushSync(); 29592 return root; 29593 } else { 29594 // First clear any existing content. 29595 var rootSibling; 29596 29597 while (rootSibling = container.lastChild) { 29598 container.removeChild(rootSibling); 29599 } 29600 29601 if (typeof callback === 'function') { 29602 var _originalCallback = callback; 29603 29604 callback = function () { 29605 var instance = getPublicRootInstance(_root); 29606 29607 _originalCallback.call(instance); 29608 }; 29609 } 29610 29611 var _root = createContainer(container, LegacyRoot, null, // hydrationCallbacks 29612 false, // isStrictMode 29613 false, // concurrentUpdatesByDefaultOverride, 29614 '', // identifierPrefix 29615 noopOnRecoverableError); 29616 29617 container._reactRootContainer = _root; 29618 markContainerAsRoot(_root.current, container); 29619 29620 var _rootContainerElement = container.nodeType === COMMENT_NODE ? container.parentNode : container; 29621 29622 listenToAllSupportedEvents(_rootContainerElement); // Initial mount should not be batched. 29623 29624 flushSync(function () { 29625 updateContainer(initialChildren, _root, parentComponent, callback); 29626 }); 29627 return _root; 29628 } 29629 } 29630 29631 function warnOnInvalidCallback$1(callback, callerName) { 29632 { 29633 if (callback !== null && typeof callback !== 'function') { 29634 error('%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback); 29635 } 29636 } 29637 } 29638 29639 function legacyRenderSubtreeIntoContainer(parentComponent, children, container, forceHydrate, callback) { 29640 { 29641 topLevelUpdateWarnings(container); 29642 warnOnInvalidCallback$1(callback === undefined ? null : callback, 'render'); 29643 } 29644 29645 var maybeRoot = container._reactRootContainer; 29646 var root; 29647 29648 if (!maybeRoot) { 29649 // Initial mount 29650 root = legacyCreateRootFromDOMContainer(container, children, parentComponent, callback, forceHydrate); 29651 } else { 29652 root = maybeRoot; 29653 29654 if (typeof callback === 'function') { 29655 var originalCallback = callback; 29656 29657 callback = function () { 29658 var instance = getPublicRootInstance(root); 29659 originalCallback.call(instance); 29660 }; 29661 } // Update 29662 29663 29664 updateContainer(children, root, parentComponent, callback); 29665 } 29666 29667 return getPublicRootInstance(root); 29668 } 29669 29670 var didWarnAboutFindDOMNode = false; 29671 function findDOMNode(componentOrElement) { 29672 { 29673 if (!didWarnAboutFindDOMNode) { 29674 didWarnAboutFindDOMNode = true; 29675 29676 error('findDOMNode is deprecated and will be removed in the next major ' + 'release. 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'); 29677 } 29678 29679 var owner = ReactCurrentOwner$3.current; 29680 29681 if (owner !== null && owner.stateNode !== null) { 29682 var warnedAboutRefsInRender = owner.stateNode._warnedAboutRefsInRender; 29683 29684 if (!warnedAboutRefsInRender) { 29685 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'); 29686 } 29687 29688 owner.stateNode._warnedAboutRefsInRender = true; 29689 } 29690 } 29691 29692 if (componentOrElement == null) { 29693 return null; 29694 } 29695 29696 if (componentOrElement.nodeType === ELEMENT_NODE) { 29697 return componentOrElement; 29698 } 29699 29700 { 29701 return findHostInstanceWithWarning(componentOrElement, 'findDOMNode'); 29702 } 29703 } 29704 function hydrate(element, container, callback) { 29705 { 29706 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'); 29707 } 29708 29709 if (!isValidContainerLegacy(container)) { 29710 throw new Error('Target container is not a DOM element.'); 29711 } 29712 29713 { 29714 var isModernRoot = isContainerMarkedAsRoot(container) && container._reactRootContainer === undefined; 29715 29716 if (isModernRoot) { 29717 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)?'); 29718 } 29719 } // TODO: throw or warn if we couldn't hydrate? 29720 29721 29722 return legacyRenderSubtreeIntoContainer(null, element, container, true, callback); 29723 } 29724 function render(element, container, callback) { 29725 { 29726 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'); 29727 } 29728 29729 if (!isValidContainerLegacy(container)) { 29730 throw new Error('Target container is not a DOM element.'); 29731 } 29732 29733 { 29734 var isModernRoot = isContainerMarkedAsRoot(container) && container._reactRootContainer === undefined; 29735 29736 if (isModernRoot) { 29737 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)?'); 29738 } 29739 } 29740 29741 return legacyRenderSubtreeIntoContainer(null, element, container, false, callback); 29742 } 29743 function unstable_renderSubtreeIntoContainer(parentComponent, element, containerNode, callback) { 29744 { 29745 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'); 29746 } 29747 29748 if (!isValidContainerLegacy(containerNode)) { 29749 throw new Error('Target container is not a DOM element.'); 29750 } 29751 29752 if (parentComponent == null || !has(parentComponent)) { 29753 throw new Error('parentComponent must be a valid React Component'); 29754 } 29755 29756 return legacyRenderSubtreeIntoContainer(parentComponent, element, containerNode, false, callback); 29757 } 29758 var didWarnAboutUnmountComponentAtNode = false; 29759 function unmountComponentAtNode(container) { 29760 { 29761 if (!didWarnAboutUnmountComponentAtNode) { 29762 didWarnAboutUnmountComponentAtNode = true; 29763 29764 error('unmountComponentAtNode is deprecated and will be removed in the ' + 'next major release. Switch to the createRoot API. Learn ' + 'more: https://reactjs.org/link/switch-to-createroot'); 29765 } 29766 } 29767 29768 if (!isValidContainerLegacy(container)) { 29769 throw new Error('unmountComponentAtNode(...): Target container is not a DOM element.'); 29770 } 29771 29772 { 29773 var isModernRoot = isContainerMarkedAsRoot(container) && container._reactRootContainer === undefined; 29774 29775 if (isModernRoot) { 29776 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()?'); 29777 } 29778 } 29779 29780 if (container._reactRootContainer) { 29781 { 29782 var rootEl = getReactRootElementInContainer(container); 29783 var renderedByDifferentReact = rootEl && !getInstanceFromNode(rootEl); 29784 29785 if (renderedByDifferentReact) { 29786 error("unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by another copy of React.'); 29787 } 29788 } // Unmount should not be batched. 29789 29790 29791 flushSync(function () { 29792 legacyRenderSubtreeIntoContainer(null, null, container, false, function () { 29793 // $FlowFixMe This should probably use `delete container._reactRootContainer` 29794 container._reactRootContainer = null; 29795 unmarkContainerAsRoot(container); 29796 }); 29797 }); // If you call unmountComponentAtNode twice in quick succession, you'll 29798 // get `true` twice. That's probably fine? 29799 29800 return true; 29801 } else { 29802 { 29803 var _rootEl = getReactRootElementInContainer(container); 29804 29805 var hasNonRootReactChild = !!(_rootEl && getInstanceFromNode(_rootEl)); // Check if the container itself is a React root node. 29806 29807 var isContainerReactRoot = container.nodeType === ELEMENT_NODE && isValidContainerLegacy(container.parentNode) && !!container.parentNode._reactRootContainer; 29808 29809 if (hasNonRootReactChild) { 29810 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.'); 29811 } 29812 } 29813 29814 return false; 29815 } 29816 } 29817 29818 setAttemptSynchronousHydration(attemptSynchronousHydration$1); 29819 setAttemptContinuousHydration(attemptContinuousHydration$1); 29820 setAttemptHydrationAtCurrentPriority(attemptHydrationAtCurrentPriority$1); 29821 setGetCurrentUpdatePriority(getCurrentUpdatePriority); 29822 setAttemptHydrationAtPriority(runWithPriority); 29823 29824 { 29825 if (typeof Map !== 'function' || // $FlowIssue Flow incorrectly thinks Map has no prototype 29826 Map.prototype == null || typeof Map.prototype.forEach !== 'function' || typeof Set !== 'function' || // $FlowIssue Flow incorrectly thinks Set has no prototype 29827 Set.prototype == null || typeof Set.prototype.clear !== 'function' || typeof Set.prototype.forEach !== 'function') { 29828 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'); 29829 } 29830 } 29831 29832 setRestoreImplementation(restoreControlledState$3); 29833 setBatchingImplementation(batchedUpdates$1, discreteUpdates, flushSync); 29834 29835 function createPortal$1(children, container) { 29836 var key = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; 29837 29838 if (!isValidContainer(container)) { 29839 throw new Error('Target container is not a DOM element.'); 29840 } // TODO: pass ReactDOM portal implementation as third argument 29841 // $FlowFixMe The Flow type is opaque but there's no way to actually create it. 29842 29843 29844 return createPortal(children, container, null, key); 29845 } 29846 29847 function renderSubtreeIntoContainer(parentComponent, element, containerNode, callback) { 29848 return unstable_renderSubtreeIntoContainer(parentComponent, element, containerNode, callback); 29849 } 29850 29851 var Internals = { 29852 usingClientEntryPoint: false, 29853 // Keep in sync with ReactTestUtils.js. 29854 // This is an array for better minification. 29855 Events: [getInstanceFromNode, getNodeFromInstance, getFiberCurrentPropsFromNode, enqueueStateRestore, restoreStateIfNeeded, batchedUpdates$1] 29856 }; 29857 29858 function createRoot$1(container, options) { 29859 { 29860 if (!Internals.usingClientEntryPoint && !true) { 29861 error('You are importing createRoot from "react-dom" which is not supported. ' + 'You should instead import it from "react-dom/client".'); 29862 } 29863 } 29864 29865 return createRoot(container, options); 29866 } 29867 29868 function hydrateRoot$1(container, initialChildren, options) { 29869 { 29870 if (!Internals.usingClientEntryPoint && !true) { 29871 error('You are importing hydrateRoot from "react-dom" which is not supported. ' + 'You should instead import it from "react-dom/client".'); 29872 } 29873 } 29874 29875 return hydrateRoot(container, initialChildren, options); 29876 } // Overload the definition to the two valid signatures. 29877 // Warning, this opts-out of checking the function body. 29878 29879 29880 // eslint-disable-next-line no-redeclare 29881 function flushSync$1(fn) { 29882 { 29883 if (isAlreadyRendering()) { 29884 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.'); 29885 } 29886 } 29887 29888 return flushSync(fn); 29889 } 29890 var foundDevTools = injectIntoDevTools({ 29891 findFiberByHostInstance: getClosestInstanceFromNode, 29892 bundleType: 1 , 29893 version: ReactVersion, 29894 rendererPackageName: 'react-dom' 29895 }); 29896 29897 { 29898 if (!foundDevTools && canUseDOM && window.top === window.self) { 29899 // If we're in Chrome or Firefox, provide a download link if not installed. 29900 if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) { 29901 var protocol = window.location.protocol; // Don't warn in exotic cases like chrome-extension://. 29902 29903 if (/^(https?|file):$/.test(protocol)) { 29904 // eslint-disable-next-line react-internal/no-production-logging 29905 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'); 29906 } 29907 } 29908 } 29909 } 29910 29911 exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = Internals; 29912 exports.createPortal = createPortal$1; 29913 exports.createRoot = createRoot$1; 29914 exports.findDOMNode = findDOMNode; 29915 exports.flushSync = flushSync$1; 29916 exports.hydrate = hydrate; 29917 exports.hydrateRoot = hydrateRoot$1; 29918 exports.render = render; 29919 exports.unmountComponentAtNode = unmountComponentAtNode; 29920 exports.unstable_batchedUpdates = batchedUpdates$1; 29921 exports.unstable_renderSubtreeIntoContainer = renderSubtreeIntoContainer; 29922 exports.version = ReactVersion; 29923 29924 })));
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Sat Nov 23 08:20:01 2024 | Cross-referenced by PHPXref |