From c7e4e4f3fbefa1ff85735a20c6c66de96157c393 Mon Sep 17 00:00:00 2001 From: hoxyq Date: Tue, 7 Nov 2023 19:06:24 +0000 Subject: [PATCH] Generate sourcemaps for production build artifacts (#26446) ## Summary This PR updates the Rollup build pipeline to generate sourcemaps for production build artifacts like `react-dom.production.min.js`. It requires the Rollup v3 changes that were just merged in #26442 . Sourcemaps are currently _only_ generated for build artifacts that are _truly_ "production" - no sourcemaps will be generated for development, profiling, UMD, or `shouldStayReadable` artifacts. The generated sourcemaps contain the bundled source contents right before that chunk was minified by Closure, and _not_ the original source files like `react-reconciler/src/*`. This better reflects the actual code that is running as part of the bundle, with all the feature flags and transformations that were applied to the source files to generate that bundle. The sourcemaps _do_ still show comments and original function names, thus improving debuggability for production usage. Fixes #20186 . This allows React users to actually debug a readable version of the React bundle in production scenarios. It also allows other tools like [Replay](https://replay.io) to do a better job inspecting the React source when stepping through. ## How did you test this change? - Generated numerous sourcemaps with various combinations of the React bundle selections - Viewed those sourcemaps in https://evanw.github.io/source-map-visualization/ and confirmed via the visualization that the generated mappings appear to be correct I've attached a set of production files + their sourcemaps here: [react-sourcemap-examples.zip](https://github.com/facebook/react/files/11023466/react-sourcemap-examples.zip) You can drag JS+sourcemap file pairs into https://evanw.github.io/source-map-visualization/ for viewing. Examples: - `react.production.min.js`: ![image](https://user-images.githubusercontent.com/1128784/226478247-e5cbdee0-83fd-4a19-bcf1-09961d3c7da4.png) - `react-dom.production.min.js`: ![image](https://user-images.githubusercontent.com/1128784/226478433-b5ccbf0f-8f68-42fe-9db9-9ecb97770d46.png) - `use-sync-external-store/with-selector.production.min.js`: ![image](https://user-images.githubusercontent.com/1128784/226478565-bc74699d-db14-4c39-9e2d-b775f8755561.png) DiffTrain build for [2c8a139a593e0294c3a6953d74b451bd05fdcfca](https://github.com/facebook/react/commit/2c8a139a593e0294c3a6953d74b451bd05fdcfca) --- .../facebook-www/JSXDEVRuntime-dev.classic.js | 2584 +- .../facebook-www/JSXDEVRuntime-dev.modern.js | 2584 +- .../JSXDEVRuntime-prod.classic.js | 22 +- .../facebook-www/JSXDEVRuntime-prod.modern.js | 22 +- .../JSXDEVRuntime-profiling.classic.js | 22 +- .../JSXDEVRuntime-profiling.modern.js | 22 +- compiled/facebook-www/REVISION | 2 +- compiled/facebook-www/React-dev.classic.js | 7157 +- compiled/facebook-www/React-dev.modern.js | 7067 +- compiled/facebook-www/React-prod.classic.js | 24 +- compiled/facebook-www/React-prod.modern.js | 24 +- .../facebook-www/React-profiling.classic.js | 51 +- .../facebook-www/React-profiling.modern.js | 51 +- compiled/facebook-www/ReactART-dev.classic.js | 51264 +++++----- compiled/facebook-www/ReactART-dev.modern.js | 50601 +++++----- .../facebook-www/ReactART-prod.classic.js | 26 +- compiled/facebook-www/ReactART-prod.modern.js | 26 +- compiled/facebook-www/ReactDOM-dev.classic.js | 82311 +++++++-------- compiled/facebook-www/ReactDOM-dev.modern.js | 81358 +++++++-------- .../facebook-www/ReactDOM-prod.classic.js | 28 +- compiled/facebook-www/ReactDOM-prod.modern.js | 28 +- .../ReactDOM-profiling.classic.js | 53 +- .../facebook-www/ReactDOM-profiling.modern.js | 53 +- .../ReactDOMServer-dev.classic.js | 24827 ++--- .../facebook-www/ReactDOMServer-dev.modern.js | 24323 ++--- .../ReactDOMServer-prod.classic.js | 24 +- .../ReactDOMServer-prod.modern.js | 24 +- .../ReactDOMServerStreaming-dev.modern.js | 23777 ++--- .../ReactDOMServerStreaming-prod.modern.js | 22 +- .../ReactDOMTesting-dev.classic.js | 84280 ++++++++-------- .../ReactDOMTesting-dev.modern.js | 82549 +++++++-------- .../ReactDOMTesting-prod.classic.js | 28 +- .../ReactDOMTesting-prod.modern.js | 28 +- .../ReactFreshRuntime-dev.classic.js | 1150 +- .../ReactFreshRuntime-dev.modern.js | 1150 +- compiled/facebook-www/ReactIs-dev.classic.js | 432 +- compiled/facebook-www/ReactIs-dev.modern.js | 432 +- compiled/facebook-www/ReactIs-prod.classic.js | 22 +- compiled/facebook-www/ReactIs-prod.modern.js | 22 +- .../ReactTestRenderer-dev.classic.js | 46479 ++++----- .../ReactTestRenderer-dev.modern.js | 46479 ++++----- .../ReactTestUtils-dev.classic.js | 3113 +- .../facebook-www/ReactTestUtils-dev.modern.js | 3113 +- .../facebook-www/Scheduler-dev.classic.js | 1516 +- compiled/facebook-www/Scheduler-dev.modern.js | 1516 +- .../facebook-www/Scheduler-prod.classic.js | 22 +- .../facebook-www/Scheduler-prod.modern.js | 22 +- .../Scheduler-profiling.classic.js | 49 +- .../Scheduler-profiling.modern.js | 49 +- .../facebook-www/SchedulerMock-dev.classic.js | 1541 +- .../facebook-www/SchedulerMock-dev.modern.js | 1541 +- .../SchedulerMock-prod.classic.js | 22 +- .../facebook-www/SchedulerMock-prod.modern.js | 22 +- .../SchedulerPostTask-dev.classic.js | 411 +- .../SchedulerPostTask-dev.modern.js | 411 +- .../SchedulerPostTask-prod.classic.js | 22 +- .../SchedulerPostTask-prod.modern.js | 22 +- .../SchedulerPostTask-profiling.classic.js | 22 +- .../SchedulerPostTask-profiling.modern.js | 22 +- .../unstable_server-external-runtime.js | 2 + 60 files changed, 320575 insertions(+), 314291 deletions(-) diff --git a/compiled/facebook-www/JSXDEVRuntime-dev.classic.js b/compiled/facebook-www/JSXDEVRuntime-dev.classic.js index c4a63224b610c..458773ed81522 100644 --- a/compiled/facebook-www/JSXDEVRuntime-dev.classic.js +++ b/compiled/facebook-www/JSXDEVRuntime-dev.classic.js @@ -1,4 +1,5 @@ /** + * @preserve * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the @@ -10,1504 +11,1533 @@ * @preserve-invariant-messages */ -'use strict'; +"use strict"; if (__DEV__) { - (function() { -"use strict"; + (function () { + "use strict"; -var React = require("react"); - -// ATTENTION -// When adding new symbols to this file, -// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' -// The Symbol used to tag the ReactElement-like types. -var REACT_ELEMENT_TYPE = Symbol.for("react.element"); -var REACT_PORTAL_TYPE = Symbol.for("react.portal"); -var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); -var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); -var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); -var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); -var REACT_CONTEXT_TYPE = Symbol.for("react.context"); -var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); -var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); -var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); -var REACT_MEMO_TYPE = Symbol.for("react.memo"); -var REACT_LAZY_TYPE = Symbol.for("react.lazy"); -var REACT_SCOPE_TYPE = Symbol.for("react.scope"); -var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); -var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); -var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); -var REACT_CACHE_TYPE = Symbol.for("react.cache"); -var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); -var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; -var FAUX_ITERATOR_SYMBOL = "@@iterator"; -function getIteratorFn(maybeIterable) { - if (maybeIterable === null || typeof maybeIterable !== "object") { - return null; - } - - var maybeIterator = - (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || - maybeIterable[FAUX_ITERATOR_SYMBOL]; - - if (typeof maybeIterator === "function") { - return maybeIterator; - } - - return null; -} + var React = require("react"); -// This refers to a WWW module. -var warningWWW = require("warning"); -function error(format) { - { - { - for ( - var _len2 = arguments.length, - args = new Array(_len2 > 1 ? _len2 - 1 : 0), - _key2 = 1; - _key2 < _len2; - _key2++ - ) { - args[_key2 - 1] = arguments[_key2]; + // ATTENTION + // When adding new symbols to this file, + // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' + // The Symbol used to tag the ReactElement-like types. + var REACT_ELEMENT_TYPE = Symbol.for("react.element"); + var REACT_PORTAL_TYPE = Symbol.for("react.portal"); + var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); + var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); + var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); + var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); + var REACT_CONTEXT_TYPE = Symbol.for("react.context"); + var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); + var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); + var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); + var REACT_MEMO_TYPE = Symbol.for("react.memo"); + var REACT_LAZY_TYPE = Symbol.for("react.lazy"); + var REACT_SCOPE_TYPE = Symbol.for("react.scope"); + var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); + var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); + var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); + var REACT_CACHE_TYPE = Symbol.for("react.cache"); + var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); + var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; + var FAUX_ITERATOR_SYMBOL = "@@iterator"; + function getIteratorFn(maybeIterable) { + if (maybeIterable === null || typeof maybeIterable !== "object") { + return null; } - printWarning("error", format, args); - } - } -} + var maybeIterator = + (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || + maybeIterable[FAUX_ITERATOR_SYMBOL]; -function printWarning(level, format, args) { - { - var React = require("react"); + if (typeof maybeIterator === "function") { + return maybeIterator; + } - var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. + return null; + } - if (ReactSharedInternals != null) { - var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - var stack = ReactDebugCurrentFrame.getStackAddendum(); + // This refers to a WWW module. + var warningWWW = require("warning"); + function error(format) { + { + { + for ( + var _len2 = arguments.length, + args = new Array(_len2 > 1 ? _len2 - 1 : 0), + _key2 = 1; + _key2 < _len2; + _key2++ + ) { + args[_key2 - 1] = arguments[_key2]; + } - if (stack !== "") { - format += "%s"; - args.push(stack); + printWarning("error", format, args); + } } - } // TODO: don't ignore level and pass it down somewhere too. - - args.unshift(format); - args.unshift(false); - warningWWW.apply(null, args); - } -} - -// Re-export dynamic flags from the www version. -var dynamicFeatureFlags = require("ReactFeatureFlags"); - -var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, - enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing; -// On WWW, false is used for a new modern build. - -var REACT_CLIENT_REFERENCE$1 = Symbol.for("react.client.reference"); -function isValidElementType(type) { - if (typeof type === "string" || typeof type === "function") { - return true; - } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill). - - if ( - type === REACT_FRAGMENT_TYPE || - type === REACT_PROFILER_TYPE || - (enableDebugTracing && type === REACT_DEBUG_TRACING_MODE_TYPE) || - type === REACT_STRICT_MODE_TYPE || - type === REACT_SUSPENSE_TYPE || - type === REACT_SUSPENSE_LIST_TYPE || - type === REACT_LEGACY_HIDDEN_TYPE || - type === REACT_OFFSCREEN_TYPE || - type === REACT_SCOPE_TYPE || - type === REACT_CACHE_TYPE || - (enableTransitionTracing && type === REACT_TRACING_MARKER_TYPE) - ) { - return true; - } - - if (typeof type === "object" && type !== null) { - if ( - type.$$typeof === REACT_LAZY_TYPE || - type.$$typeof === REACT_MEMO_TYPE || - type.$$typeof === REACT_PROVIDER_TYPE || - type.$$typeof === REACT_CONTEXT_TYPE || - type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object - // types supported by any Flight configuration anywhere since - // we don't know which Flight build this will end up being used - // with. - type.$$typeof === REACT_CLIENT_REFERENCE$1 || - type.getModuleId !== undefined - ) { - return true; } - } - return false; -} + function printWarning(level, format, args) { + { + var React = require("react"); -function getWrappedName(outerType, innerType, wrapperName) { - var displayName = outerType.displayName; - - if (displayName) { - return displayName; - } - - var functionName = innerType.displayName || innerType.name || ""; - return functionName !== "" - ? wrapperName + "(" + functionName + ")" - : wrapperName; -} // Keep in sync with react-reconciler/getComponentNameFromFiber - -function getContextName(type) { - return type.displayName || "Context"; -} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. - -function getComponentNameFromType(type) { - if (type == null) { - // Host root, text node or just invalid type. - return null; - } - - { - if (typeof type.tag === "number") { - error( - "Received an unexpected object in getComponentNameFromType(). " + - "This is likely a bug in React. Please file an issue." - ); - } - } + var ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. - if (typeof type === "function") { - return type.displayName || type.name || null; - } + if (ReactSharedInternals != null) { + var ReactDebugCurrentFrame = + ReactSharedInternals.ReactDebugCurrentFrame; + var stack = ReactDebugCurrentFrame.getStackAddendum(); - if (typeof type === "string") { - return type; - } + if (stack !== "") { + format += "%s"; + args.push(stack); + } + } // TODO: don't ignore level and pass it down somewhere too. - switch (type) { - case REACT_FRAGMENT_TYPE: - return "Fragment"; + args.unshift(format); + args.unshift(false); + warningWWW.apply(null, args); + } + } - case REACT_PORTAL_TYPE: - return "Portal"; + // Re-export dynamic flags from the www version. + var dynamicFeatureFlags = require("ReactFeatureFlags"); - case REACT_PROFILER_TYPE: - return "Profiler"; + var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, + enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing; + // On WWW, false is used for a new modern build. - case REACT_STRICT_MODE_TYPE: - return "StrictMode"; + var REACT_CLIENT_REFERENCE$1 = Symbol.for("react.client.reference"); + function isValidElementType(type) { + if (typeof type === "string" || typeof type === "function") { + return true; + } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill). - case REACT_SUSPENSE_TYPE: - return "Suspense"; + if ( + type === REACT_FRAGMENT_TYPE || + type === REACT_PROFILER_TYPE || + (enableDebugTracing && type === REACT_DEBUG_TRACING_MODE_TYPE) || + type === REACT_STRICT_MODE_TYPE || + type === REACT_SUSPENSE_TYPE || + type === REACT_SUSPENSE_LIST_TYPE || + type === REACT_LEGACY_HIDDEN_TYPE || + type === REACT_OFFSCREEN_TYPE || + type === REACT_SCOPE_TYPE || + type === REACT_CACHE_TYPE || + (enableTransitionTracing && type === REACT_TRACING_MARKER_TYPE) + ) { + return true; + } - case REACT_SUSPENSE_LIST_TYPE: - return "SuspenseList"; + if (typeof type === "object" && type !== null) { + if ( + type.$$typeof === REACT_LAZY_TYPE || + type.$$typeof === REACT_MEMO_TYPE || + type.$$typeof === REACT_PROVIDER_TYPE || + type.$$typeof === REACT_CONTEXT_TYPE || + type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object + // types supported by any Flight configuration anywhere since + // we don't know which Flight build this will end up being used + // with. + type.$$typeof === REACT_CLIENT_REFERENCE$1 || + type.getModuleId !== undefined + ) { + return true; + } + } - case REACT_CACHE_TYPE: { - return "Cache"; + return false; } - // Fall through + function getWrappedName(outerType, innerType, wrapperName) { + var displayName = outerType.displayName; - case REACT_TRACING_MARKER_TYPE: - if (enableTransitionTracing) { - return "TracingMarker"; + if (displayName) { + return displayName; } - } - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_CONTEXT_TYPE: - var context = type; - return getContextName(context) + ".Consumer"; + var functionName = innerType.displayName || innerType.name || ""; + return functionName !== "" + ? wrapperName + "(" + functionName + ")" + : wrapperName; + } // Keep in sync with react-reconciler/getComponentNameFromFiber - case REACT_PROVIDER_TYPE: - var provider = type; - return getContextName(provider._context) + ".Provider"; + function getContextName(type) { + return type.displayName || "Context"; + } // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. - case REACT_FORWARD_REF_TYPE: - return getWrappedName(type, type.render, "ForwardRef"); - - case REACT_MEMO_TYPE: - var outerName = type.displayName || null; + function getComponentNameFromType(type) { + if (type == null) { + // Host root, text node or just invalid type. + return null; + } - if (outerName !== null) { - return outerName; + { + if (typeof type.tag === "number") { + error( + "Received an unexpected object in getComponentNameFromType(). " + + "This is likely a bug in React. Please file an issue." + ); } + } - return getComponentNameFromType(type.type) || "Memo"; - - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + if (typeof type === "function") { + return type.displayName || type.name || null; + } - try { - return getComponentNameFromType(init(payload)); - } catch (x) { - return null; - } + if (typeof type === "string") { + return type; } - } - } - return null; -} + switch (type) { + case REACT_FRAGMENT_TYPE: + return "Fragment"; -var assign = Object.assign; - -// Helpers to patch console.logs to avoid logging during side-effect free -// replaying on render function. This currently only patches the object -// lazily which won't cover if the log function was extracted eagerly. -// We could also eagerly patch the method. -var disabledDepth = 0; -var prevLog; -var prevInfo; -var prevWarn; -var prevError; -var prevGroup; -var prevGroupCollapsed; -var prevGroupEnd; - -function disabledLog() {} - -disabledLog.__reactDisabledLog = true; -function disableLogs() { - { - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - prevLog = console.log; - prevInfo = console.info; - prevWarn = console.warn; - prevError = console.error; - prevGroup = console.group; - prevGroupCollapsed = console.groupCollapsed; - prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 - - var props = { - configurable: true, - enumerable: true, - value: disabledLog, - writable: true - }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. - - Object.defineProperties(console, { - info: props, - log: props, - warn: props, - error: props, - group: props, - groupCollapsed: props, - groupEnd: props - }); - /* eslint-enable react-internal/no-production-logging */ - } + case REACT_PORTAL_TYPE: + return "Portal"; - disabledDepth++; - } -} -function reenableLogs() { - { - disabledDepth--; - - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - var props = { - configurable: true, - enumerable: true, - writable: true - }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. - - Object.defineProperties(console, { - log: assign({}, props, { - value: prevLog - }), - info: assign({}, props, { - value: prevInfo - }), - warn: assign({}, props, { - value: prevWarn - }), - error: assign({}, props, { - value: prevError - }), - group: assign({}, props, { - value: prevGroup - }), - groupCollapsed: assign({}, props, { - value: prevGroupCollapsed - }), - groupEnd: assign({}, props, { - value: prevGroupEnd - }) - }); - /* eslint-enable react-internal/no-production-logging */ - } + case REACT_PROFILER_TYPE: + return "Profiler"; - if (disabledDepth < 0) { - error( - "disabledDepth fell below zero. " + - "This is a bug in React. Please file an issue." - ); - } - } -} + case REACT_STRICT_MODE_TYPE: + return "StrictMode"; -var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; + case REACT_SUSPENSE_TYPE: + return "Suspense"; -var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; -var prefix; -function describeBuiltInComponentFrame(name, source, ownerFn) { - { - if (prefix === undefined) { - // Extract the VM specific prefix used by each line. - try { - throw Error(); - } catch (x) { - var match = x.stack.trim().match(/\n( *(at )?)/); - prefix = (match && match[1]) || ""; - } - } // We use the prefix to ensure our stacks line up with native stack frames. + case REACT_SUSPENSE_LIST_TYPE: + return "SuspenseList"; - return "\n" + prefix + name; - } -} -var reentry = false; -var componentFrameCache; + case REACT_CACHE_TYPE: { + return "Cache"; + } -{ - var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; - componentFrameCache = new PossiblyWeakMap(); -} + // Fall through -function describeNativeComponentFrame(fn, construct) { - // If something asked for a stack inside a fake render, it should get ignored. - if (!fn || reentry) { - return ""; - } + case REACT_TRACING_MARKER_TYPE: + if (enableTransitionTracing) { + return "TracingMarker"; + } + } - { - var frame = componentFrameCache.get(fn); + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_CONTEXT_TYPE: + var context = type; + return getContextName(context) + ".Consumer"; - if (frame !== undefined) { - return frame; - } - } - - var control; - reentry = true; - var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. - - Error.prepareStackTrace = undefined; - var previousDispatcher; - - { - previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function - // for warnings. - - ReactCurrentDispatcher.current = null; - disableLogs(); - } - - try { - // This should throw. - if (construct) { - // Something should be setting the props in the constructor. - var Fake = function () { - throw Error(); - }; // $FlowFixMe[prop-missing] - - Object.defineProperty(Fake.prototype, "props", { - set: function () { - // We use a throwing setter instead of frozen or non-writable props - // because that won't throw in a non-strict mode function. - throw Error(); - } - }); + case REACT_PROVIDER_TYPE: + var provider = type; + return getContextName(provider._context) + ".Provider"; - if (typeof Reflect === "object" && Reflect.construct) { - // We construct a different control for this case to include any extra - // frames added by the construct call. - try { - Reflect.construct(Fake, []); - } catch (x) { - control = x; - } + case REACT_FORWARD_REF_TYPE: + return getWrappedName(type, type.render, "ForwardRef"); - Reflect.construct(fn, [], Fake); - } else { - try { - Fake.call(); - } catch (x) { - control = x; - } // $FlowFixMe[prop-missing] found when upgrading Flow + case REACT_MEMO_TYPE: + var outerName = type.displayName || null; - fn.call(Fake.prototype); - } - } else { - try { - throw Error(); - } catch (x) { - control = x; - } // TODO(luna): This will currently only throw if the function component - // tries to access React/ReactDOM/props. We should probably make this throw - // in simple components too - - var maybePromise = fn(); // If the function component returns a promise, it's likely an async - // component, which we don't yet support. Attach a noop catch handler to - // silence the error. - // TODO: Implement component stacks for async client components? - - if (maybePromise && typeof maybePromise.catch === "function") { - maybePromise.catch(function () {}); - } - } - } catch (sample) { - // This is inlined manually because closure doesn't do it for us. - if (sample && control && typeof sample.stack === "string") { - // This extracts the first frame from the sample that isn't also in the control. - // Skipping one frame that we assume is the frame that calls the two. - var sampleLines = sample.stack.split("\n"); - var controlLines = control.stack.split("\n"); - var s = sampleLines.length - 1; - var c = controlLines.length - 1; - - while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { - // We expect at least one stack frame to be shared. - // Typically this will be the root most one. However, stack frames may be - // cut off due to maximum stack limits. In this case, one maybe cut off - // earlier than the other. We assume that the sample is longer or the same - // and there for cut off earlier. So we should find the root most frame in - // the sample somewhere in the control. - c--; - } + if (outerName !== null) { + return outerName; + } - for (; s >= 1 && c >= 0; s--, c--) { - // Next we find the first one that isn't the same which should be the - // frame that called our sample function and the control. - if (sampleLines[s] !== controlLines[c]) { - // In V8, the first line is describing the message but other VMs don't. - // If we're about to return the first line, and the control is also on the same - // line, that's a pretty good indicator that our sample threw at same line as - // the control. I.e. before we entered the sample frame. So we ignore this result. - // This can happen if you passed a class to function component, or non-function. - if (s !== 1 || c !== 1) { - do { - s--; - c--; // We may still have similar intermediate frames from the construct call. - // The next one that isn't the same should be our match though. - - if (c < 0 || sampleLines[s] !== controlLines[c]) { - // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. - var _frame = "\n" + sampleLines[s].replace(" at new ", " at "); // If our component frame is labeled "" - // but we have a user-provided "displayName" - // splice it in to make the stack more readable. - - if (fn.displayName && _frame.includes("")) { - _frame = _frame.replace("", fn.displayName); - } + return getComponentNameFromType(type.type) || "Memo"; - { - if (typeof fn === "function") { - componentFrameCache.set(fn, _frame); - } - } // Return the line we found. + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - return _frame; - } - } while (s >= 1 && c >= 0); + try { + return getComponentNameFromType(init(payload)); + } catch (x) { + return null; + } } - - break; } } - } - } finally { - reentry = false; - { - ReactCurrentDispatcher.current = previousDispatcher; - reenableLogs(); + return null; } - Error.prepareStackTrace = previousPrepareStackTrace; - } // Fallback to just using the name if we couldn't make it throw. + var assign = Object.assign; + + // Helpers to patch console.logs to avoid logging during side-effect free + // replaying on render function. This currently only patches the object + // lazily which won't cover if the log function was extracted eagerly. + // We could also eagerly patch the method. + var disabledDepth = 0; + var prevLog; + var prevInfo; + var prevWarn; + var prevError; + var prevGroup; + var prevGroupCollapsed; + var prevGroupEnd; + + function disabledLog() {} + + disabledLog.__reactDisabledLog = true; + function disableLogs() { + { + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + prevLog = console.log; + prevInfo = console.info; + prevWarn = console.warn; + prevError = console.error; + prevGroup = console.group; + prevGroupCollapsed = console.groupCollapsed; + prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 + + var props = { + configurable: true, + enumerable: true, + value: disabledLog, + writable: true + }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. + + Object.defineProperties(console, { + info: props, + log: props, + warn: props, + error: props, + group: props, + groupCollapsed: props, + groupEnd: props + }); + /* eslint-enable react-internal/no-production-logging */ + } - var name = fn ? fn.displayName || fn.name : ""; - var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ""; + disabledDepth++; + } + } + function reenableLogs() { + { + disabledDepth--; + + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + var props = { + configurable: true, + enumerable: true, + writable: true + }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. + + Object.defineProperties(console, { + log: assign({}, props, { + value: prevLog + }), + info: assign({}, props, { + value: prevInfo + }), + warn: assign({}, props, { + value: prevWarn + }), + error: assign({}, props, { + value: prevError + }), + group: assign({}, props, { + value: prevGroup + }), + groupCollapsed: assign({}, props, { + value: prevGroupCollapsed + }), + groupEnd: assign({}, props, { + value: prevGroupEnd + }) + }); + /* eslint-enable react-internal/no-production-logging */ + } - { - if (typeof fn === "function") { - componentFrameCache.set(fn, syntheticFrame); + if (disabledDepth < 0) { + error( + "disabledDepth fell below zero. " + + "This is a bug in React. Please file an issue." + ); + } + } } - } - return syntheticFrame; -} -function describeFunctionComponentFrame(fn, source, ownerFn) { - { - return describeNativeComponentFrame(fn, false); - } -} + var ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; -function shouldConstruct(Component) { - var prototype = Component.prototype; - return !!(prototype && prototype.isReactComponent); -} + var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; + var prefix; + function describeBuiltInComponentFrame(name, source, ownerFn) { + { + if (prefix === undefined) { + // Extract the VM specific prefix used by each line. + try { + throw Error(); + } catch (x) { + var match = x.stack.trim().match(/\n( *(at )?)/); + prefix = (match && match[1]) || ""; + } + } // We use the prefix to ensure our stacks line up with native stack frames. -function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { - if (type == null) { - return ""; - } + return "\n" + prefix + name; + } + } + var reentry = false; + var componentFrameCache; - if (typeof type === "function") { { - return describeNativeComponentFrame(type, shouldConstruct(type)); + var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; + componentFrameCache = new PossiblyWeakMap(); } - } - if (typeof type === "string") { - return describeBuiltInComponentFrame(type); - } + function describeNativeComponentFrame(fn, construct) { + // If something asked for a stack inside a fake render, it should get ignored. + if (!fn || reentry) { + return ""; + } - switch (type) { - case REACT_SUSPENSE_TYPE: - return describeBuiltInComponentFrame("Suspense"); + { + var frame = componentFrameCache.get(fn); - case REACT_SUSPENSE_LIST_TYPE: - return describeBuiltInComponentFrame("SuspenseList"); - } + if (frame !== undefined) { + return frame; + } + } - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_FORWARD_REF_TYPE: - return describeFunctionComponentFrame(type.render); + var control; + reentry = true; + var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. - case REACT_MEMO_TYPE: - // Memo may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); + Error.prepareStackTrace = undefined; + var previousDispatcher; - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + { + previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function + // for warnings. - try { - // Lazy may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV( - init(payload), - source, - ownerFn - ); - } catch (x) {} + ReactCurrentDispatcher.current = null; + disableLogs(); } - } - } - - return ""; -} -// $FlowFixMe[method-unbinding] -var hasOwnProperty = Object.prototype.hasOwnProperty; - -var loggedTypeFailures = {}; -var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; - -function setCurrentlyValidatingElement$1(element) { - { - if (element) { - var owner = element._owner; - var stack = describeUnknownElementTypeFrameInDEV( - element.type, - element._source, - owner ? owner.type : null - ); - ReactDebugCurrentFrame$1.setExtraStackFrame(stack); - } else { - ReactDebugCurrentFrame$1.setExtraStackFrame(null); - } - } -} - -function checkPropTypes(typeSpecs, values, location, componentName, element) { - { - // $FlowFixMe[incompatible-use] This is okay but Flow doesn't know it. - var has = Function.call.bind(hasOwnProperty); + try { + // This should throw. + if (construct) { + // Something should be setting the props in the constructor. + var Fake = function () { + throw Error(); + }; // $FlowFixMe[prop-missing] + + Object.defineProperty(Fake.prototype, "props", { + set: function () { + // We use a throwing setter instead of frozen or non-writable props + // because that won't throw in a non-strict mode function. + throw Error(); + } + }); + + if (typeof Reflect === "object" && Reflect.construct) { + // We construct a different control for this case to include any extra + // frames added by the construct call. + try { + Reflect.construct(Fake, []); + } catch (x) { + control = x; + } - for (var typeSpecName in typeSpecs) { - if (has(typeSpecs, typeSpecName)) { - var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to - // fail the render phase where it didn't fail before. So we log it. - // After these have been cleaned up, we'll let them throw. + Reflect.construct(fn, [], Fake); + } else { + try { + Fake.call(); + } catch (x) { + control = x; + } // $FlowFixMe[prop-missing] found when upgrading Flow - try { - // This is intentionally an invariant that gets caught. It's the same - // behavior as without this statement except with a better message. - if (typeof typeSpecs[typeSpecName] !== "function") { - // eslint-disable-next-line react-internal/prod-error-codes - 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`." - ); - err.name = "Invariant Violation"; - throw err; + fn.call(Fake.prototype); + } + } else { + try { + throw Error(); + } catch (x) { + control = x; + } // TODO(luna): This will currently only throw if the function component + // tries to access React/ReactDOM/props. We should probably make this throw + // in simple components too + + var maybePromise = fn(); // If the function component returns a promise, it's likely an async + // component, which we don't yet support. Attach a noop catch handler to + // silence the error. + // TODO: Implement component stacks for async client components? + + if (maybePromise && typeof maybePromise.catch === "function") { + maybePromise.catch(function () {}); } - - error$1 = typeSpecs[typeSpecName]( - values, - typeSpecName, - componentName, - location, - null, - "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" - ); - } catch (ex) { - error$1 = ex; } + } catch (sample) { + // This is inlined manually because closure doesn't do it for us. + if (sample && control && typeof sample.stack === "string") { + // This extracts the first frame from the sample that isn't also in the control. + // Skipping one frame that we assume is the frame that calls the two. + var sampleLines = sample.stack.split("\n"); + var controlLines = control.stack.split("\n"); + var s = sampleLines.length - 1; + var c = controlLines.length - 1; + + while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { + // We expect at least one stack frame to be shared. + // Typically this will be the root most one. However, stack frames may be + // cut off due to maximum stack limits. In this case, one maybe cut off + // earlier than the other. We assume that the sample is longer or the same + // and there for cut off earlier. So we should find the root most frame in + // the sample somewhere in the control. + c--; + } - if (error$1 && !(error$1 instanceof Error)) { - setCurrentlyValidatingElement$1(element); + for (; s >= 1 && c >= 0; s--, c--) { + // Next we find the first one that isn't the same which should be the + // frame that called our sample function and the control. + if (sampleLines[s] !== controlLines[c]) { + // In V8, the first line is describing the message but other VMs don't. + // If we're about to return the first line, and the control is also on the same + // line, that's a pretty good indicator that our sample threw at same line as + // the control. I.e. before we entered the sample frame. So we ignore this result. + // This can happen if you passed a class to function component, or non-function. + if (s !== 1 || c !== 1) { + do { + s--; + c--; // We may still have similar intermediate frames from the construct call. + // The next one that isn't the same should be our match though. + + if (c < 0 || sampleLines[s] !== controlLines[c]) { + // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. + var _frame = + "\n" + sampleLines[s].replace(" at new ", " at "); // If our component frame is labeled "" + // but we have a user-provided "displayName" + // splice it in to make the stack more readable. + + if (fn.displayName && _frame.includes("")) { + _frame = _frame.replace("", fn.displayName); + } + + { + if (typeof fn === "function") { + componentFrameCache.set(fn, _frame); + } + } // Return the line we found. + + return _frame; + } + } while (s >= 1 && c >= 0); + } - 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 - ); + break; + } + } + } + } finally { + reentry = false; - setCurrentlyValidatingElement$1(null); + { + ReactCurrentDispatcher.current = previousDispatcher; + reenableLogs(); } - if ( - error$1 instanceof Error && - !(error$1.message in loggedTypeFailures) - ) { - // Only monitor this failure once because there tends to be a lot of the - // same error. - loggedTypeFailures[error$1.message] = true; - setCurrentlyValidatingElement$1(element); + Error.prepareStackTrace = previousPrepareStackTrace; + } // Fallback to just using the name if we couldn't make it throw. - error("Failed %s type: %s", location, error$1.message); + var name = fn ? fn.displayName || fn.name : ""; + var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ""; - setCurrentlyValidatingElement$1(null); + { + if (typeof fn === "function") { + componentFrameCache.set(fn, syntheticFrame); } } + + return syntheticFrame; + } + function describeFunctionComponentFrame(fn, source, ownerFn) { + { + return describeNativeComponentFrame(fn, false); + } } - } -} -var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare + function shouldConstruct(Component) { + var prototype = Component.prototype; + return !!(prototype && prototype.isReactComponent); + } -function isArray(a) { - return isArrayImpl(a); -} + function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { + if (type == null) { + return ""; + } -/* - * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol - * and Temporal.* types. See https://github.com/facebook/react/pull/22064. - * - * The functions in this module will throw an easier-to-understand, - * easier-to-debug exception with a clear errors message message explaining the - * problem. (Instead of a confusing exception thrown inside the implementation - * of the `value` object). - */ -// $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. -function typeName(value) { - { - // toStringTag is needed for namespaced types like Temporal.Instant - var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; - var type = - (hasToStringTag && value[Symbol.toStringTag]) || - value.constructor.name || - "Object"; // $FlowFixMe[incompatible-return] - - return type; - } -} // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - -function willCoercionThrow(value) { - { - try { - testStringCoercion(value); - return false; - } catch (e) { - return true; - } - } -} + if (typeof type === "function") { + { + return describeNativeComponentFrame(type, shouldConstruct(type)); + } + } -function testStringCoercion(value) { - // If you ended up here by following an exception call stack, here's what's - // happened: you supplied an object or symbol value to React (as a prop, key, - // DOM attribute, CSS property, string ref, etc.) and when React tried to - // coerce it to a string using `'' + value`, an exception was thrown. - // - // The most common types that will cause this exception are `Symbol` instances - // and Temporal objects like `Temporal.Instant`. But any object that has a - // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this - // exception. (Library authors do this to prevent users from using built-in - // numeric operators like `+` or comparison operators like `>=` because custom - // methods are needed to perform accurate arithmetic or comparison.) - // - // To fix the problem, coerce this object or symbol value to a string before - // passing it to React. The most reliable way is usually `String(value)`. - // - // To find which value is throwing, check the browser or debugger console. - // Before this exception was thrown, there should be `console.error` output - // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the - // problem and how that type was used: key, atrribute, input value prop, etc. - // In most cases, this console output also shows the component and its - // ancestor components where the exception happened. - // - // eslint-disable-next-line react-internal/safe-string-coercion - return "" + value; -} -function checkKeyStringCoercion(value) { - { - if (willCoercionThrow(value)) { - error( - "The provided key is an unsupported type %s." + - " This value must be coerced to a string before using it here.", - typeName(value) - ); - - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) - } - } -} + if (typeof type === "string") { + return describeBuiltInComponentFrame(type); + } -var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; -var RESERVED_PROPS = { - key: true, - ref: true, - __self: true, - __source: true -}; -var specialPropKeyWarningShown; -var specialPropRefWarningShown; -var didWarnAboutStringRefs; - -{ - didWarnAboutStringRefs = {}; -} + switch (type) { + case REACT_SUSPENSE_TYPE: + return describeBuiltInComponentFrame("Suspense"); -function hasValidRef(config) { - { - if (hasOwnProperty.call(config, "ref")) { - var getter = Object.getOwnPropertyDescriptor(config, "ref").get; + case REACT_SUSPENSE_LIST_TYPE: + return describeBuiltInComponentFrame("SuspenseList"); + } - if (getter && getter.isReactWarning) { - return false; + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_FORWARD_REF_TYPE: + return describeFunctionComponentFrame(type.render); + + case REACT_MEMO_TYPE: + // Memo may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + type.type, + source, + ownerFn + ); + + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; + + try { + // Lazy may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + init(payload), + source, + ownerFn + ); + } catch (x) {} + } + } } + + return ""; } - } - return config.ref !== undefined; -} + // $FlowFixMe[method-unbinding] + var hasOwnProperty = Object.prototype.hasOwnProperty; -function hasValidKey(config) { - { - if (hasOwnProperty.call(config, "key")) { - var getter = Object.getOwnPropertyDescriptor(config, "key").get; + var loggedTypeFailures = {}; + var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; - if (getter && getter.isReactWarning) { - return false; + function setCurrentlyValidatingElement$1(element) { + { + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV( + element.type, + element._source, + owner ? owner.type : null + ); + ReactDebugCurrentFrame$1.setExtraStackFrame(stack); + } else { + ReactDebugCurrentFrame$1.setExtraStackFrame(null); + } } } - } - return config.key !== undefined; -} - -function warnIfStringRefCannotBeAutoConverted(config, self) { - { - if ( - typeof config.ref === "string" && - ReactCurrentOwner$1.current && - self && - ReactCurrentOwner$1.current.stateNode !== self + function checkPropTypes( + typeSpecs, + values, + location, + componentName, + element ) { - var componentName = getComponentNameFromType( - ReactCurrentOwner$1.current.type - ); + { + // $FlowFixMe[incompatible-use] This is okay but Flow doesn't know it. + var has = Function.call.bind(hasOwnProperty); + + for (var typeSpecName in typeSpecs) { + if (has(typeSpecs, typeSpecName)) { + var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to + // fail the render phase where it didn't fail before. So we log it. + // After these have been cleaned up, we'll let them throw. + + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + if (typeof typeSpecs[typeSpecName] !== "function") { + // eslint-disable-next-line react-internal/prod-error-codes + 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`." + ); + err.name = "Invariant Violation"; + throw err; + } - if (!didWarnAboutStringRefs[componentName]) { - error( - 'Component "%s" contains the string ref "%s". ' + - "Support for string refs will be removed in a future major release. " + - "This case cannot be automatically converted to an arrow function. " + - "We ask you to manually fix this case by using useRef() or createRef() instead. " + - "Learn more about using refs safely here: " + - "https://reactjs.org/link/strict-mode-string-ref", - getComponentNameFromType(ReactCurrentOwner$1.current.type), - config.ref - ); + error$1 = typeSpecs[typeSpecName]( + values, + typeSpecName, + componentName, + location, + null, + "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" + ); + } catch (ex) { + error$1 = ex; + } - didWarnAboutStringRefs[componentName] = true; - } - } - } -} + if (error$1 && !(error$1 instanceof Error)) { + setCurrentlyValidatingElement$1(element); + + 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 + ); + + setCurrentlyValidatingElement$1(null); + } -function defineKeyPropWarningGetter(props, displayName) { - { - var warnAboutAccessingKey = function () { - if (!specialPropKeyWarningShown) { - specialPropKeyWarningShown = true; + if ( + error$1 instanceof Error && + !(error$1.message in loggedTypeFailures) + ) { + // Only monitor this failure once because there tends to be a lot of the + // same error. + loggedTypeFailures[error$1.message] = true; + setCurrentlyValidatingElement$1(element); - error( - "%s: `key` is not a prop. Trying to access it will result " + - "in `undefined` being returned. If you need to access the same " + - "value within the child component, you should pass it as a different " + - "prop. (https://reactjs.org/link/special-props)", - displayName - ); + error("Failed %s type: %s", location, error$1.message); + + setCurrentlyValidatingElement$1(null); + } + } + } } - }; + } - warnAboutAccessingKey.isReactWarning = true; - Object.defineProperty(props, "key", { - get: warnAboutAccessingKey, - configurable: true - }); - } -} + var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare -function defineRefPropWarningGetter(props, displayName) { - { - var warnAboutAccessingRef = function () { - if (!specialPropRefWarningShown) { - specialPropRefWarningShown = true; + function isArray(a) { + return isArrayImpl(a); + } - error( - "%s: `ref` is not a prop. Trying to access it will result " + - "in `undefined` being returned. If you need to access the same " + - "value within the child component, you should pass it as a different " + - "prop. (https://reactjs.org/link/special-props)", - displayName - ); + /* + * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol + * and Temporal.* types. See https://github.com/facebook/react/pull/22064. + * + * The functions in this module will throw an easier-to-understand, + * easier-to-debug exception with a clear errors message message explaining the + * problem. (Instead of a confusing exception thrown inside the implementation + * of the `value` object). + */ + // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. + function typeName(value) { + { + // toStringTag is needed for namespaced types like Temporal.Instant + var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; + var type = + (hasToStringTag && value[Symbol.toStringTag]) || + value.constructor.name || + "Object"; // $FlowFixMe[incompatible-return] + + return type; } - }; + } // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - warnAboutAccessingRef.isReactWarning = true; - Object.defineProperty(props, "ref", { - get: warnAboutAccessingRef, - configurable: true - }); - } -} -/** - * Factory method to create a new React element. This no longer adheres to - * the class pattern, so do not use new to call it. Also, instanceof check - * will not work. Instead test $$typeof field against Symbol.for('react.element') to check - * if something is a React Element. - * - * @param {*} type - * @param {*} props - * @param {*} key - * @param {string|object} ref - * @param {*} owner - * @param {*} self A *temporary* helper to detect places where `this` is - * different from the `owner` when React.createElement is called, so that we - * can warn. We want to get rid of owner and replace string `ref`s with arrow - * functions, and as long as `this` and owner are the same, there will be no - * change in behavior. - * @param {*} source An annotation object (added by a transpiler or otherwise) - * indicating filename, line number, and/or other information. - * @internal - */ + function willCoercionThrow(value) { + { + try { + testStringCoercion(value); + return false; + } catch (e) { + return true; + } + } + } -function ReactElement(type, key, ref, self, source, owner, props) { - var element = { - // This tag allows us to uniquely identify this as a React Element - $$typeof: REACT_ELEMENT_TYPE, - // Built-in properties that belong on the element - type: type, - key: key, - ref: ref, - props: props, - // Record the component responsible for creating this element. - _owner: owner - }; - - { - // The validation flag is currently mutative. We put it on - // an external backing store so that we can freeze the whole object. - // This can be replaced with a WeakMap once they are implemented in - // commonly used development environments. - element._store = {}; // To make comparing ReactElements easier for testing purposes, we make - // the validation flag non-enumerable (where possible, which should - // include every environment we run tests in), so the test framework - // ignores it. - - Object.defineProperty(element._store, "validated", { - configurable: false, - enumerable: false, - writable: true, - value: false - }); // self and source are DEV only properties. - - Object.defineProperty(element, "_self", { - configurable: false, - enumerable: false, - writable: false, - value: self - }); // Two elements created in two different places should be considered - // equal for testing purposes and therefore we hide it from enumeration. - - Object.defineProperty(element, "_source", { - configurable: false, - enumerable: false, - writable: false, - value: source - }); - - if (Object.freeze) { - Object.freeze(element.props); - Object.freeze(element); + function testStringCoercion(value) { + // If you ended up here by following an exception call stack, here's what's + // happened: you supplied an object or symbol value to React (as a prop, key, + // DOM attribute, CSS property, string ref, etc.) and when React tried to + // coerce it to a string using `'' + value`, an exception was thrown. + // + // The most common types that will cause this exception are `Symbol` instances + // and Temporal objects like `Temporal.Instant`. But any object that has a + // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this + // exception. (Library authors do this to prevent users from using built-in + // numeric operators like `+` or comparison operators like `>=` because custom + // methods are needed to perform accurate arithmetic or comparison.) + // + // To fix the problem, coerce this object or symbol value to a string before + // passing it to React. The most reliable way is usually `String(value)`. + // + // To find which value is throwing, check the browser or debugger console. + // Before this exception was thrown, there should be `console.error` output + // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the + // problem and how that type was used: key, atrribute, input value prop, etc. + // In most cases, this console output also shows the component and its + // ancestor components where the exception happened. + // + // eslint-disable-next-line react-internal/safe-string-coercion + return "" + value; } - } + function checkKeyStringCoercion(value) { + { + if (willCoercionThrow(value)) { + error( + "The provided key is an unsupported type %s." + + " This value must be coerced to a string before using it here.", + typeName(value) + ); - return element; -} -/** - * https://github.com/reactjs/rfcs/pull/107 - * @param {*} type - * @param {object} props - * @param {string} key - */ + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + } + } + } -function jsxDEV$1(type, config, maybeKey, source, self) { - { - var propName; // Reserved names are extracted + var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; + var RESERVED_PROPS = { + key: true, + ref: true, + __self: true, + __source: true + }; + var specialPropKeyWarningShown; + var specialPropRefWarningShown; + var didWarnAboutStringRefs; - var props = {}; - var key = null; - var ref = null; // Currently, key can be spread in as a prop. This causes a potential - // issue if key is also explicitly declared (ie.
- // or
). We want to deprecate key spread, - // but as an intermediary step, we will use jsxDEV for everything except - //
, because we aren't currently able to tell if - // key is explicitly declared to be undefined or not. + { + didWarnAboutStringRefs = {}; + } - if (maybeKey !== undefined) { + function hasValidRef(config) { { - checkKeyStringCoercion(maybeKey); + if (hasOwnProperty.call(config, "ref")) { + var getter = Object.getOwnPropertyDescriptor(config, "ref").get; + + if (getter && getter.isReactWarning) { + return false; + } + } } - key = "" + maybeKey; + return config.ref !== undefined; } - if (hasValidKey(config)) { + function hasValidKey(config) { { - checkKeyStringCoercion(config.key); + if (hasOwnProperty.call(config, "key")) { + var getter = Object.getOwnPropertyDescriptor(config, "key").get; + + if (getter && getter.isReactWarning) { + return false; + } + } } - key = "" + config.key; + return config.key !== undefined; } - if (hasValidRef(config)) { - ref = config.ref; - warnIfStringRefCannotBeAutoConverted(config, self); - } // Remaining properties are added to a new props object - - for (propName in config) { - if ( - hasOwnProperty.call(config, propName) && - !RESERVED_PROPS.hasOwnProperty(propName) - ) { - props[propName] = config[propName]; - } - } // Resolve default props + function warnIfStringRefCannotBeAutoConverted(config, self) { + { + if ( + typeof config.ref === "string" && + ReactCurrentOwner$1.current && + self && + ReactCurrentOwner$1.current.stateNode !== self + ) { + var componentName = getComponentNameFromType( + ReactCurrentOwner$1.current.type + ); - if (type && type.defaultProps) { - var defaultProps = type.defaultProps; + if (!didWarnAboutStringRefs[componentName]) { + error( + 'Component "%s" contains the string ref "%s". ' + + "Support for string refs will be removed in a future major release. " + + "This case cannot be automatically converted to an arrow function. " + + "We ask you to manually fix this case by using useRef() or createRef() instead. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-string-ref", + getComponentNameFromType(ReactCurrentOwner$1.current.type), + config.ref + ); - for (propName in defaultProps) { - if (props[propName] === undefined) { - props[propName] = defaultProps[propName]; + didWarnAboutStringRefs[componentName] = true; + } } } } - if (key || ref) { - var displayName = - typeof type === "function" - ? type.displayName || type.name || "Unknown" - : type; + function defineKeyPropWarningGetter(props, displayName) { + { + var warnAboutAccessingKey = function () { + if (!specialPropKeyWarningShown) { + specialPropKeyWarningShown = true; - if (key) { - defineKeyPropWarningGetter(props, displayName); - } + error( + "%s: `key` is not a prop. Trying to access it will result " + + "in `undefined` being returned. If you need to access the same " + + "value within the child component, you should pass it as a different " + + "prop. (https://reactjs.org/link/special-props)", + displayName + ); + } + }; - if (ref) { - defineRefPropWarningGetter(props, displayName); + warnAboutAccessingKey.isReactWarning = true; + Object.defineProperty(props, "key", { + get: warnAboutAccessingKey, + configurable: true + }); } } - return ReactElement( - type, - key, - ref, - self, - source, - ReactCurrentOwner$1.current, - props - ); - } -} + function defineRefPropWarningGetter(props, displayName) { + { + var warnAboutAccessingRef = function () { + if (!specialPropRefWarningShown) { + specialPropRefWarningShown = true; + + error( + "%s: `ref` is not a prop. Trying to access it will result " + + "in `undefined` being returned. If you need to access the same " + + "value within the child component, you should pass it as a different " + + "prop. (https://reactjs.org/link/special-props)", + displayName + ); + } + }; -var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; -var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; -var REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"); - -function setCurrentlyValidatingElement(element) { - { - if (element) { - var owner = element._owner; - var stack = describeUnknownElementTypeFrameInDEV( - element.type, - element._source, - owner ? owner.type : null - ); - ReactDebugCurrentFrame.setExtraStackFrame(stack); - } else { - ReactDebugCurrentFrame.setExtraStackFrame(null); + warnAboutAccessingRef.isReactWarning = true; + Object.defineProperty(props, "ref", { + get: warnAboutAccessingRef, + configurable: true + }); + } } - } -} + /** + * Factory method to create a new React element. This no longer adheres to + * the class pattern, so do not use new to call it. Also, instanceof check + * will not work. Instead test $$typeof field against Symbol.for('react.element') to check + * if something is a React Element. + * + * @param {*} type + * @param {*} props + * @param {*} key + * @param {string|object} ref + * @param {*} owner + * @param {*} self A *temporary* helper to detect places where `this` is + * different from the `owner` when React.createElement is called, so that we + * can warn. We want to get rid of owner and replace string `ref`s with arrow + * functions, and as long as `this` and owner are the same, there will be no + * change in behavior. + * @param {*} source An annotation object (added by a transpiler or otherwise) + * indicating filename, line number, and/or other information. + * @internal + */ + + function ReactElement(type, key, ref, self, source, owner, props) { + var element = { + // This tag allows us to uniquely identify this as a React Element + $$typeof: REACT_ELEMENT_TYPE, + // Built-in properties that belong on the element + type: type, + key: key, + ref: ref, + props: props, + // Record the component responsible for creating this element. + _owner: owner + }; -var propTypesMisspellWarningShown; + { + // The validation flag is currently mutative. We put it on + // an external backing store so that we can freeze the whole object. + // This can be replaced with a WeakMap once they are implemented in + // commonly used development environments. + element._store = {}; // To make comparing ReactElements easier for testing purposes, we make + // the validation flag non-enumerable (where possible, which should + // include every environment we run tests in), so the test framework + // ignores it. + + Object.defineProperty(element._store, "validated", { + configurable: false, + enumerable: false, + writable: true, + value: false + }); // self and source are DEV only properties. + + Object.defineProperty(element, "_self", { + configurable: false, + enumerable: false, + writable: false, + value: self + }); // Two elements created in two different places should be considered + // equal for testing purposes and therefore we hide it from enumeration. + + Object.defineProperty(element, "_source", { + configurable: false, + enumerable: false, + writable: false, + value: source + }); + + if (Object.freeze) { + Object.freeze(element.props); + Object.freeze(element); + } + } -{ - propTypesMisspellWarningShown = false; -} -/** - * Verifies the object is a ReactElement. - * See https://reactjs.org/docs/react-api.html#isvalidelement - * @param {?object} object - * @return {boolean} True if `object` is a ReactElement. - * @final - */ + return element; + } + /** + * https://github.com/reactjs/rfcs/pull/107 + * @param {*} type + * @param {object} props + * @param {string} key + */ + + function jsxDEV$1(type, config, maybeKey, source, self) { + { + var propName; // Reserved names are extracted + + var props = {}; + var key = null; + var ref = null; // Currently, key can be spread in as a prop. This causes a potential + // issue if key is also explicitly declared (ie.
+ // or
). We want to deprecate key spread, + // but as an intermediary step, we will use jsxDEV for everything except + //
, because we aren't currently able to tell if + // key is explicitly declared to be undefined or not. + + if (maybeKey !== undefined) { + { + checkKeyStringCoercion(maybeKey); + } -function isValidElement(object) { - { - return ( - typeof object === "object" && - object !== null && - object.$$typeof === REACT_ELEMENT_TYPE - ); - } -} + key = "" + maybeKey; + } -function getDeclarationErrorAddendum() { - { - if (ReactCurrentOwner.current) { - var name = getComponentNameFromType(ReactCurrentOwner.current.type); + if (hasValidKey(config)) { + { + checkKeyStringCoercion(config.key); + } - if (name) { - return "\n\nCheck the render method of `" + name + "`."; - } - } + key = "" + config.key; + } - return ""; - } -} + if (hasValidRef(config)) { + ref = config.ref; + warnIfStringRefCannotBeAutoConverted(config, self); + } // Remaining properties are added to a new props object + + for (propName in config) { + if ( + hasOwnProperty.call(config, propName) && + !RESERVED_PROPS.hasOwnProperty(propName) + ) { + props[propName] = config[propName]; + } + } // Resolve default props -function getSourceInfoErrorAddendum(source) { - { - if (source !== undefined) { - var fileName = source.fileName.replace(/^.*[\\\/]/, ""); - var lineNumber = source.lineNumber; - return "\n\nCheck your code at " + fileName + ":" + lineNumber + "."; - } + if (type && type.defaultProps) { + var defaultProps = type.defaultProps; - return ""; - } -} -/** - * Warn if there's no key explicitly set on dynamic arrays of children or - * object keys are not valid. This allows us to keep track of children between - * updates. - */ + for (propName in defaultProps) { + if (props[propName] === undefined) { + props[propName] = defaultProps[propName]; + } + } + } -var ownerHasKeyUseWarning = {}; + if (key || ref) { + var displayName = + typeof type === "function" + ? type.displayName || type.name || "Unknown" + : type; -function getCurrentComponentErrorInfo(parentType) { - { - var info = getDeclarationErrorAddendum(); + if (key) { + defineKeyPropWarningGetter(props, displayName); + } - if (!info) { - var parentName = - typeof parentType === "string" - ? parentType - : parentType.displayName || parentType.name; + if (ref) { + defineRefPropWarningGetter(props, displayName); + } + } - if (parentName) { - info = - "\n\nCheck the top-level render call using <" + parentName + ">."; + return ReactElement( + type, + key, + ref, + self, + source, + ReactCurrentOwner$1.current, + props + ); } } - return info; - } -} -/** - * Warn if the element doesn't have an explicit key assigned to it. - * This element is in an array. The array could grow and shrink or be - * reordered. All children that haven't already been validated are required to - * have a "key" property assigned to it. Error statuses are cached so a warning - * will only be shown once. - * - * @internal - * @param {ReactElement} element Element that requires a key. - * @param {*} parentType element's parent's type. - */ + var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + var REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"); -function validateExplicitKey(element, parentType) { - { - if (!element._store || element._store.validated || element.key != null) { - return; + function setCurrentlyValidatingElement(element) { + { + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV( + element.type, + element._source, + owner ? owner.type : null + ); + ReactDebugCurrentFrame.setExtraStackFrame(stack); + } else { + ReactDebugCurrentFrame.setExtraStackFrame(null); + } + } } - element._store.validated = true; - var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType); + var propTypesMisspellWarningShown; - if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { - return; + { + propTypesMisspellWarningShown = false; } - - ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a - // property, it may be the creator of the child that's responsible for - // assigning it a key. - - var childOwner = ""; - - if ( - element && - element._owner && - element._owner !== ReactCurrentOwner.current - ) { - // Give the component that originally created this child. - childOwner = - " It was passed a child from " + - getComponentNameFromType(element._owner.type) + - "."; + /** + * Verifies the object is a ReactElement. + * See https://reactjs.org/docs/react-api.html#isvalidelement + * @param {?object} object + * @return {boolean} True if `object` is a ReactElement. + * @final + */ + + function isValidElement(object) { + { + return ( + typeof object === "object" && + object !== null && + object.$$typeof === REACT_ELEMENT_TYPE + ); + } } - setCurrentlyValidatingElement(element); - - error( - 'Each child in a list should have a unique "key" prop.' + - "%s%s See https://reactjs.org/link/warning-keys for more information.", - currentComponentErrorInfo, - childOwner - ); + function getDeclarationErrorAddendum() { + { + if (ReactCurrentOwner.current) { + var name = getComponentNameFromType(ReactCurrentOwner.current.type); - setCurrentlyValidatingElement(null); - } -} -/** - * Ensure that every element either is passed in a static location, in an - * array with an explicit keys property defined, or in an object literal - * with valid key property. - * - * @internal - * @param {ReactNode} node Statically passed child of any type. - * @param {*} parentType node's parent's type. - */ + if (name) { + return "\n\nCheck the render method of `" + name + "`."; + } + } -function validateChildKeys(node, parentType) { - { - if (typeof node !== "object" || !node) { - return; + return ""; + } } - if (node.$$typeof === REACT_CLIENT_REFERENCE); - else if (isArray(node)) { - for (var i = 0; i < node.length; i++) { - var child = node[i]; - - if (isValidElement(child)) { - validateExplicitKey(child, parentType); - } - } - } else if (isValidElement(node)) { - // This element was passed in a valid location. - if (node._store) { - node._store.validated = true; - } - } else { - var iteratorFn = getIteratorFn(node); - - if (typeof iteratorFn === "function") { - // Entry iterators used to provide implicit keys, - // but now we print a separate warning for them later. - if (iteratorFn !== node.entries) { - var iterator = iteratorFn.call(node); - var step; - - while (!(step = iterator.next()).done) { - if (isValidElement(step.value)) { - validateExplicitKey(step.value, parentType); - } - } + function getSourceInfoErrorAddendum(source) { + { + if (source !== undefined) { + var fileName = source.fileName.replace(/^.*[\\\/]/, ""); + var lineNumber = source.lineNumber; + return "\n\nCheck your code at " + fileName + ":" + lineNumber + "."; } + + return ""; } } - } -} -/** - * Given an element, validate that its props follow the propTypes definition, - * provided by the type. - * - * @param {ReactElement} element - */ + /** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ -function validatePropTypes(element) { - { - var type = element.type; + var ownerHasKeyUseWarning = {}; - if (type === null || type === undefined || typeof type === "string") { - return; - } + function getCurrentComponentErrorInfo(parentType) { + { + var info = getDeclarationErrorAddendum(); - if (type.$$typeof === REACT_CLIENT_REFERENCE) { - return; - } + if (!info) { + var parentName = + typeof parentType === "string" + ? parentType + : parentType.displayName || parentType.name; - var propTypes; + if (parentName) { + info = + "\n\nCheck the top-level render call using <" + parentName + ">."; + } + } - if (typeof type === "function") { - propTypes = type.propTypes; - } else if ( - typeof type === "object" && - (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here. - // Inner props are checked in the reconciler. - type.$$typeof === REACT_MEMO_TYPE) - ) { - propTypes = type.propTypes; - } else { - return; + return info; + } } + /** + * Warn if the element doesn't have an explicit key assigned to it. + * This element is in an array. The array could grow and shrink or be + * reordered. All children that haven't already been validated are required to + * have a "key" property assigned to it. Error statuses are cached so a warning + * will only be shown once. + * + * @internal + * @param {ReactElement} element Element that requires a key. + * @param {*} parentType element's parent's type. + */ + + function validateExplicitKey(element, parentType) { + { + if ( + !element._store || + element._store.validated || + element.key != null + ) { + return; + } - if (propTypes) { - // Intentionally inside to avoid triggering lazy initializers: - var name = getComponentNameFromType(type); - checkPropTypes(propTypes, element.props, "prop", name, element); - } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) { - propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers: - - var _name = getComponentNameFromType(type); + element._store.validated = true; + var currentComponentErrorInfo = + getCurrentComponentErrorInfo(parentType); - error( - "Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?", - _name || "Unknown" - ); - } + if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { + return; + } - if ( - typeof type.getDefaultProps === "function" && - !type.getDefaultProps.isReactClassApproved - ) { - error( - "getDefaultProps is only used on classic React.createClass " + - "definitions. Use a static property named `defaultProps` instead." - ); - } - } -} -/** - * Given a fragment, validate that it can only be provided with fragment props - * @param {ReactElement} fragment - */ + ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a + // property, it may be the creator of the child that's responsible for + // assigning it a key. -function validateFragmentProps(fragment) { - { - var keys = Object.keys(fragment.props); + var childOwner = ""; - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; + if ( + element && + element._owner && + element._owner !== ReactCurrentOwner.current + ) { + // Give the component that originally created this child. + childOwner = + " It was passed a child from " + + getComponentNameFromType(element._owner.type) + + "."; + } - if (key !== "children" && key !== "key") { - setCurrentlyValidatingElement(fragment); + setCurrentlyValidatingElement(element); error( - "Invalid prop `%s` supplied to `React.Fragment`. " + - "React.Fragment can only have `key` and `children` props.", - key + 'Each child in a list should have a unique "key" prop.' + + "%s%s See https://reactjs.org/link/warning-keys for more information.", + currentComponentErrorInfo, + childOwner ); setCurrentlyValidatingElement(null); - break; } } + /** + * Ensure that every element either is passed in a static location, in an + * array with an explicit keys property defined, or in an object literal + * with valid key property. + * + * @internal + * @param {ReactNode} node Statically passed child of any type. + * @param {*} parentType node's parent's type. + */ + + function validateChildKeys(node, parentType) { + { + if (typeof node !== "object" || !node) { + return; + } - if (fragment.ref !== null) { - setCurrentlyValidatingElement(fragment); - - error("Invalid attribute `ref` supplied to `React.Fragment`."); + if (node.$$typeof === REACT_CLIENT_REFERENCE); + else if (isArray(node)) { + for (var i = 0; i < node.length; i++) { + var child = node[i]; - setCurrentlyValidatingElement(null); + if (isValidElement(child)) { + validateExplicitKey(child, parentType); + } + } + } else if (isValidElement(node)) { + // This element was passed in a valid location. + if (node._store) { + node._store.validated = true; + } + } else { + var iteratorFn = getIteratorFn(node); + + if (typeof iteratorFn === "function") { + // Entry iterators used to provide implicit keys, + // but now we print a separate warning for them later. + if (iteratorFn !== node.entries) { + var iterator = iteratorFn.call(node); + var step; + + while (!(step = iterator.next()).done) { + if (isValidElement(step.value)) { + validateExplicitKey(step.value, parentType); + } + } + } + } + } + } } - } -} + /** + * Given an element, validate that its props follow the propTypes definition, + * provided by the type. + * + * @param {ReactElement} element + */ + + function validatePropTypes(element) { + { + var type = element.type; -var didWarnAboutKeySpread = {}; -function jsxWithValidation(type, props, key, isStaticChildren, source, self) { - { - var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to - // succeed and there will likely be errors in render. + if (type === null || type === undefined || typeof type === "string") { + return; + } - if (!validType) { - var info = ""; + if (type.$$typeof === REACT_CLIENT_REFERENCE) { + return; + } - if ( - type === undefined || - (typeof type === "object" && - type !== null && - Object.keys(type).length === 0) - ) { - 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."; - } + var propTypes; - var sourceInfo = getSourceInfoErrorAddendum(source); + if (typeof type === "function") { + propTypes = type.propTypes; + } else if ( + typeof type === "object" && + (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here. + // Inner props are checked in the reconciler. + type.$$typeof === REACT_MEMO_TYPE) + ) { + propTypes = type.propTypes; + } else { + return; + } - if (sourceInfo) { - info += sourceInfo; - } else { - info += getDeclarationErrorAddendum(); - } + if (propTypes) { + // Intentionally inside to avoid triggering lazy initializers: + var name = getComponentNameFromType(type); + checkPropTypes(propTypes, element.props, "prop", name, element); + } else if ( + type.PropTypes !== undefined && + !propTypesMisspellWarningShown + ) { + propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers: - var typeString; - - if (type === null) { - typeString = "null"; - } else if (isArray(type)) { - typeString = "array"; - } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) { - typeString = - "<" + (getComponentNameFromType(type.type) || "Unknown") + " />"; - info = - " Did you accidentally export a JSX literal instead of a component?"; - } else { - typeString = typeof type; - } + var _name = getComponentNameFromType(type); + + error( + "Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?", + _name || "Unknown" + ); + } - error( - "React.jsx: type is invalid -- expected a string (for " + - "built-in components) or a class/function (for composite " + - "components) but got: %s.%s", - typeString, - info - ); + if ( + typeof type.getDefaultProps === "function" && + !type.getDefaultProps.isReactClassApproved + ) { + error( + "getDefaultProps is only used on classic React.createClass " + + "definitions. Use a static property named `defaultProps` instead." + ); + } + } } + /** + * Given a fragment, validate that it can only be provided with fragment props + * @param {ReactElement} fragment + */ - var element = jsxDEV$1(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used. - // TODO: Drop this when these are no longer allowed as the type argument. + function validateFragmentProps(fragment) { + { + var keys = Object.keys(fragment.props); - if (element == null) { - return element; - } // Skip key warning if the type isn't valid since our key validation logic - // doesn't expect a non-string/function type and can throw confusing errors. - // We don't want exception behavior to differ between dev and prod. - // (Rendering will throw with a helpful message and as soon as the type is - // fixed, the key warnings will appear.) - - if (validType) { - var children = props.children; - - if (children !== undefined) { - if (isStaticChildren) { - if (isArray(children)) { - for (var i = 0; i < children.length; i++) { - validateChildKeys(children[i], type); - } + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + + if (key !== "children" && key !== "key") { + setCurrentlyValidatingElement(fragment); - if (Object.freeze) { - Object.freeze(children); - } - } else { error( - "React.jsx: Static children should always be an array. " + - "You are likely explicitly calling React.jsxs or React.jsxDEV. " + - "Use the Babel transform instead." + "Invalid prop `%s` supplied to `React.Fragment`. " + + "React.Fragment can only have `key` and `children` props.", + key ); + + setCurrentlyValidatingElement(null); + break; } - } else { - validateChildKeys(children, type); + } + + if (fragment.ref !== null) { + setCurrentlyValidatingElement(fragment); + + error("Invalid attribute `ref` supplied to `React.Fragment`."); + + setCurrentlyValidatingElement(null); } } } - if (hasOwnProperty.call(props, "key")) { - var componentName = getComponentNameFromType(type); - var keys = Object.keys(props).filter(function (k) { - return k !== "key"; - }); - var beforeExample = - keys.length > 0 - ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" - : "{key: someKey}"; + var didWarnAboutKeySpread = {}; + function jsxWithValidation( + type, + props, + key, + isStaticChildren, + source, + self + ) { + { + var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to + // succeed and there will likely be errors in render. + + if (!validType) { + var info = ""; + + if ( + type === undefined || + (typeof type === "object" && + type !== null && + Object.keys(type).length === 0) + ) { + 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."; + } - if (!didWarnAboutKeySpread[componentName + beforeExample]) { - var afterExample = - keys.length > 0 ? "{" + keys.join(": ..., ") + ": ...}" : "{}"; + var sourceInfo = getSourceInfoErrorAddendum(source); - error( - 'A props object containing a "key" prop is being spread into JSX:\n' + - " let props = %s;\n" + - " <%s {...props} />\n" + - "React keys must be passed directly to JSX without using spread:\n" + - " let props = %s;\n" + - " <%s key={someKey} {...props} />", - beforeExample, - componentName, - afterExample, - componentName - ); + if (sourceInfo) { + info += sourceInfo; + } else { + info += getDeclarationErrorAddendum(); + } - didWarnAboutKeySpread[componentName + beforeExample] = true; - } - } + var typeString; + + if (type === null) { + typeString = "null"; + } else if (isArray(type)) { + typeString = "array"; + } else if ( + type !== undefined && + type.$$typeof === REACT_ELEMENT_TYPE + ) { + typeString = + "<" + (getComponentNameFromType(type.type) || "Unknown") + " />"; + info = + " Did you accidentally export a JSX literal instead of a component?"; + } else { + typeString = typeof type; + } - if (type === REACT_FRAGMENT_TYPE) { - validateFragmentProps(element); - } else { - validatePropTypes(element); - } + error( + "React.jsx: type is invalid -- expected a string (for " + + "built-in components) or a class/function (for composite " + + "components) but got: %s.%s", + typeString, + info + ); + } - return element; - } -} // These two functions exist to still get child warnings in dev + var element = jsxDEV$1(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used. + // TODO: Drop this when these are no longer allowed as the type argument. + + if (element == null) { + return element; + } // Skip key warning if the type isn't valid since our key validation logic + // doesn't expect a non-string/function type and can throw confusing errors. + // We don't want exception behavior to differ between dev and prod. + // (Rendering will throw with a helpful message and as soon as the type is + // fixed, the key warnings will appear.) + + if (validType) { + var children = props.children; + + if (children !== undefined) { + if (isStaticChildren) { + if (isArray(children)) { + for (var i = 0; i < children.length; i++) { + validateChildKeys(children[i], type); + } + + if (Object.freeze) { + Object.freeze(children); + } + } else { + error( + "React.jsx: Static children should always be an array. " + + "You are likely explicitly calling React.jsxs or React.jsxDEV. " + + "Use the Babel transform instead." + ); + } + } else { + validateChildKeys(children, type); + } + } + } -var jsxDEV = jsxWithValidation; + if (hasOwnProperty.call(props, "key")) { + var componentName = getComponentNameFromType(type); + var keys = Object.keys(props).filter(function (k) { + return k !== "key"; + }); + var beforeExample = + keys.length > 0 + ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" + : "{key: someKey}"; + + if (!didWarnAboutKeySpread[componentName + beforeExample]) { + var afterExample = + keys.length > 0 ? "{" + keys.join(": ..., ") + ": ...}" : "{}"; + + error( + 'A props object containing a "key" prop is being spread into JSX:\n' + + " let props = %s;\n" + + " <%s {...props} />\n" + + "React keys must be passed directly to JSX without using spread:\n" + + " let props = %s;\n" + + " <%s key={someKey} {...props} />", + beforeExample, + componentName, + afterExample, + componentName + ); + + didWarnAboutKeySpread[componentName + beforeExample] = true; + } + } + + if (type === REACT_FRAGMENT_TYPE) { + validateFragmentProps(element); + } else { + validatePropTypes(element); + } + + return element; + } + } // These two functions exist to still get child warnings in dev -exports.Fragment = REACT_FRAGMENT_TYPE; -exports.jsxDEV = jsxDEV; + var jsxDEV = jsxWithValidation; + exports.Fragment = REACT_FRAGMENT_TYPE; + exports.jsxDEV = jsxDEV; })(); } diff --git a/compiled/facebook-www/JSXDEVRuntime-dev.modern.js b/compiled/facebook-www/JSXDEVRuntime-dev.modern.js index b31f278179477..016231939e8f0 100644 --- a/compiled/facebook-www/JSXDEVRuntime-dev.modern.js +++ b/compiled/facebook-www/JSXDEVRuntime-dev.modern.js @@ -1,4 +1,5 @@ /** + * @preserve * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the @@ -10,1504 +11,1533 @@ * @preserve-invariant-messages */ -'use strict'; +"use strict"; if (__DEV__) { - (function() { -"use strict"; + (function () { + "use strict"; -var React = require("react"); - -// ATTENTION -// When adding new symbols to this file, -// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' -// The Symbol used to tag the ReactElement-like types. -var REACT_ELEMENT_TYPE = Symbol.for("react.element"); -var REACT_PORTAL_TYPE = Symbol.for("react.portal"); -var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); -var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); -var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); -var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); -var REACT_CONTEXT_TYPE = Symbol.for("react.context"); -var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); -var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); -var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); -var REACT_MEMO_TYPE = Symbol.for("react.memo"); -var REACT_LAZY_TYPE = Symbol.for("react.lazy"); -var REACT_SCOPE_TYPE = Symbol.for("react.scope"); -var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); -var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); -var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); -var REACT_CACHE_TYPE = Symbol.for("react.cache"); -var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); -var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; -var FAUX_ITERATOR_SYMBOL = "@@iterator"; -function getIteratorFn(maybeIterable) { - if (maybeIterable === null || typeof maybeIterable !== "object") { - return null; - } - - var maybeIterator = - (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || - maybeIterable[FAUX_ITERATOR_SYMBOL]; - - if (typeof maybeIterator === "function") { - return maybeIterator; - } - - return null; -} + var React = require("react"); -// This refers to a WWW module. -var warningWWW = require("warning"); -function error(format) { - { - { - for ( - var _len2 = arguments.length, - args = new Array(_len2 > 1 ? _len2 - 1 : 0), - _key2 = 1; - _key2 < _len2; - _key2++ - ) { - args[_key2 - 1] = arguments[_key2]; + // ATTENTION + // When adding new symbols to this file, + // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' + // The Symbol used to tag the ReactElement-like types. + var REACT_ELEMENT_TYPE = Symbol.for("react.element"); + var REACT_PORTAL_TYPE = Symbol.for("react.portal"); + var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); + var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); + var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); + var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); + var REACT_CONTEXT_TYPE = Symbol.for("react.context"); + var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); + var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); + var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); + var REACT_MEMO_TYPE = Symbol.for("react.memo"); + var REACT_LAZY_TYPE = Symbol.for("react.lazy"); + var REACT_SCOPE_TYPE = Symbol.for("react.scope"); + var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); + var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); + var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); + var REACT_CACHE_TYPE = Symbol.for("react.cache"); + var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); + var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; + var FAUX_ITERATOR_SYMBOL = "@@iterator"; + function getIteratorFn(maybeIterable) { + if (maybeIterable === null || typeof maybeIterable !== "object") { + return null; } - printWarning("error", format, args); - } - } -} + var maybeIterator = + (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || + maybeIterable[FAUX_ITERATOR_SYMBOL]; -function printWarning(level, format, args) { - { - var React = require("react"); + if (typeof maybeIterator === "function") { + return maybeIterator; + } - var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. + return null; + } - if (ReactSharedInternals != null) { - var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - var stack = ReactDebugCurrentFrame.getStackAddendum(); + // This refers to a WWW module. + var warningWWW = require("warning"); + function error(format) { + { + { + for ( + var _len2 = arguments.length, + args = new Array(_len2 > 1 ? _len2 - 1 : 0), + _key2 = 1; + _key2 < _len2; + _key2++ + ) { + args[_key2 - 1] = arguments[_key2]; + } - if (stack !== "") { - format += "%s"; - args.push(stack); + printWarning("error", format, args); + } } - } // TODO: don't ignore level and pass it down somewhere too. - - args.unshift(format); - args.unshift(false); - warningWWW.apply(null, args); - } -} - -// Re-export dynamic flags from the www version. -var dynamicFeatureFlags = require("ReactFeatureFlags"); - -var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, - enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing; -// On WWW, true is used for a new modern build. - -var REACT_CLIENT_REFERENCE$1 = Symbol.for("react.client.reference"); -function isValidElementType(type) { - if (typeof type === "string" || typeof type === "function") { - return true; - } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill). - - if ( - type === REACT_FRAGMENT_TYPE || - type === REACT_PROFILER_TYPE || - (enableDebugTracing && type === REACT_DEBUG_TRACING_MODE_TYPE) || - type === REACT_STRICT_MODE_TYPE || - type === REACT_SUSPENSE_TYPE || - type === REACT_SUSPENSE_LIST_TYPE || - type === REACT_LEGACY_HIDDEN_TYPE || - type === REACT_OFFSCREEN_TYPE || - type === REACT_SCOPE_TYPE || - type === REACT_CACHE_TYPE || - (enableTransitionTracing && type === REACT_TRACING_MARKER_TYPE) - ) { - return true; - } - - if (typeof type === "object" && type !== null) { - if ( - type.$$typeof === REACT_LAZY_TYPE || - type.$$typeof === REACT_MEMO_TYPE || - type.$$typeof === REACT_PROVIDER_TYPE || - type.$$typeof === REACT_CONTEXT_TYPE || - type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object - // types supported by any Flight configuration anywhere since - // we don't know which Flight build this will end up being used - // with. - type.$$typeof === REACT_CLIENT_REFERENCE$1 || - type.getModuleId !== undefined - ) { - return true; } - } - return false; -} + function printWarning(level, format, args) { + { + var React = require("react"); -function getWrappedName(outerType, innerType, wrapperName) { - var displayName = outerType.displayName; - - if (displayName) { - return displayName; - } - - var functionName = innerType.displayName || innerType.name || ""; - return functionName !== "" - ? wrapperName + "(" + functionName + ")" - : wrapperName; -} // Keep in sync with react-reconciler/getComponentNameFromFiber - -function getContextName(type) { - return type.displayName || "Context"; -} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. - -function getComponentNameFromType(type) { - if (type == null) { - // Host root, text node or just invalid type. - return null; - } - - { - if (typeof type.tag === "number") { - error( - "Received an unexpected object in getComponentNameFromType(). " + - "This is likely a bug in React. Please file an issue." - ); - } - } + var ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. - if (typeof type === "function") { - return type.displayName || type.name || null; - } + if (ReactSharedInternals != null) { + var ReactDebugCurrentFrame = + ReactSharedInternals.ReactDebugCurrentFrame; + var stack = ReactDebugCurrentFrame.getStackAddendum(); - if (typeof type === "string") { - return type; - } + if (stack !== "") { + format += "%s"; + args.push(stack); + } + } // TODO: don't ignore level and pass it down somewhere too. - switch (type) { - case REACT_FRAGMENT_TYPE: - return "Fragment"; + args.unshift(format); + args.unshift(false); + warningWWW.apply(null, args); + } + } - case REACT_PORTAL_TYPE: - return "Portal"; + // Re-export dynamic flags from the www version. + var dynamicFeatureFlags = require("ReactFeatureFlags"); - case REACT_PROFILER_TYPE: - return "Profiler"; + var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, + enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing; + // On WWW, true is used for a new modern build. - case REACT_STRICT_MODE_TYPE: - return "StrictMode"; + var REACT_CLIENT_REFERENCE$1 = Symbol.for("react.client.reference"); + function isValidElementType(type) { + if (typeof type === "string" || typeof type === "function") { + return true; + } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill). - case REACT_SUSPENSE_TYPE: - return "Suspense"; + if ( + type === REACT_FRAGMENT_TYPE || + type === REACT_PROFILER_TYPE || + (enableDebugTracing && type === REACT_DEBUG_TRACING_MODE_TYPE) || + type === REACT_STRICT_MODE_TYPE || + type === REACT_SUSPENSE_TYPE || + type === REACT_SUSPENSE_LIST_TYPE || + type === REACT_LEGACY_HIDDEN_TYPE || + type === REACT_OFFSCREEN_TYPE || + type === REACT_SCOPE_TYPE || + type === REACT_CACHE_TYPE || + (enableTransitionTracing && type === REACT_TRACING_MARKER_TYPE) + ) { + return true; + } - case REACT_SUSPENSE_LIST_TYPE: - return "SuspenseList"; + if (typeof type === "object" && type !== null) { + if ( + type.$$typeof === REACT_LAZY_TYPE || + type.$$typeof === REACT_MEMO_TYPE || + type.$$typeof === REACT_PROVIDER_TYPE || + type.$$typeof === REACT_CONTEXT_TYPE || + type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object + // types supported by any Flight configuration anywhere since + // we don't know which Flight build this will end up being used + // with. + type.$$typeof === REACT_CLIENT_REFERENCE$1 || + type.getModuleId !== undefined + ) { + return true; + } + } - case REACT_CACHE_TYPE: { - return "Cache"; + return false; } - // Fall through + function getWrappedName(outerType, innerType, wrapperName) { + var displayName = outerType.displayName; - case REACT_TRACING_MARKER_TYPE: - if (enableTransitionTracing) { - return "TracingMarker"; + if (displayName) { + return displayName; } - } - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_CONTEXT_TYPE: - var context = type; - return getContextName(context) + ".Consumer"; + var functionName = innerType.displayName || innerType.name || ""; + return functionName !== "" + ? wrapperName + "(" + functionName + ")" + : wrapperName; + } // Keep in sync with react-reconciler/getComponentNameFromFiber - case REACT_PROVIDER_TYPE: - var provider = type; - return getContextName(provider._context) + ".Provider"; + function getContextName(type) { + return type.displayName || "Context"; + } // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. - case REACT_FORWARD_REF_TYPE: - return getWrappedName(type, type.render, "ForwardRef"); - - case REACT_MEMO_TYPE: - var outerName = type.displayName || null; + function getComponentNameFromType(type) { + if (type == null) { + // Host root, text node or just invalid type. + return null; + } - if (outerName !== null) { - return outerName; + { + if (typeof type.tag === "number") { + error( + "Received an unexpected object in getComponentNameFromType(). " + + "This is likely a bug in React. Please file an issue." + ); } + } - return getComponentNameFromType(type.type) || "Memo"; - - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + if (typeof type === "function") { + return type.displayName || type.name || null; + } - try { - return getComponentNameFromType(init(payload)); - } catch (x) { - return null; - } + if (typeof type === "string") { + return type; } - } - } - return null; -} + switch (type) { + case REACT_FRAGMENT_TYPE: + return "Fragment"; -var assign = Object.assign; - -// Helpers to patch console.logs to avoid logging during side-effect free -// replaying on render function. This currently only patches the object -// lazily which won't cover if the log function was extracted eagerly. -// We could also eagerly patch the method. -var disabledDepth = 0; -var prevLog; -var prevInfo; -var prevWarn; -var prevError; -var prevGroup; -var prevGroupCollapsed; -var prevGroupEnd; - -function disabledLog() {} - -disabledLog.__reactDisabledLog = true; -function disableLogs() { - { - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - prevLog = console.log; - prevInfo = console.info; - prevWarn = console.warn; - prevError = console.error; - prevGroup = console.group; - prevGroupCollapsed = console.groupCollapsed; - prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 - - var props = { - configurable: true, - enumerable: true, - value: disabledLog, - writable: true - }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. - - Object.defineProperties(console, { - info: props, - log: props, - warn: props, - error: props, - group: props, - groupCollapsed: props, - groupEnd: props - }); - /* eslint-enable react-internal/no-production-logging */ - } + case REACT_PORTAL_TYPE: + return "Portal"; - disabledDepth++; - } -} -function reenableLogs() { - { - disabledDepth--; - - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - var props = { - configurable: true, - enumerable: true, - writable: true - }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. - - Object.defineProperties(console, { - log: assign({}, props, { - value: prevLog - }), - info: assign({}, props, { - value: prevInfo - }), - warn: assign({}, props, { - value: prevWarn - }), - error: assign({}, props, { - value: prevError - }), - group: assign({}, props, { - value: prevGroup - }), - groupCollapsed: assign({}, props, { - value: prevGroupCollapsed - }), - groupEnd: assign({}, props, { - value: prevGroupEnd - }) - }); - /* eslint-enable react-internal/no-production-logging */ - } + case REACT_PROFILER_TYPE: + return "Profiler"; - if (disabledDepth < 0) { - error( - "disabledDepth fell below zero. " + - "This is a bug in React. Please file an issue." - ); - } - } -} + case REACT_STRICT_MODE_TYPE: + return "StrictMode"; -var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; + case REACT_SUSPENSE_TYPE: + return "Suspense"; -var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; -var prefix; -function describeBuiltInComponentFrame(name, source, ownerFn) { - { - if (prefix === undefined) { - // Extract the VM specific prefix used by each line. - try { - throw Error(); - } catch (x) { - var match = x.stack.trim().match(/\n( *(at )?)/); - prefix = (match && match[1]) || ""; - } - } // We use the prefix to ensure our stacks line up with native stack frames. + case REACT_SUSPENSE_LIST_TYPE: + return "SuspenseList"; - return "\n" + prefix + name; - } -} -var reentry = false; -var componentFrameCache; + case REACT_CACHE_TYPE: { + return "Cache"; + } -{ - var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; - componentFrameCache = new PossiblyWeakMap(); -} + // Fall through -function describeNativeComponentFrame(fn, construct) { - // If something asked for a stack inside a fake render, it should get ignored. - if (!fn || reentry) { - return ""; - } + case REACT_TRACING_MARKER_TYPE: + if (enableTransitionTracing) { + return "TracingMarker"; + } + } - { - var frame = componentFrameCache.get(fn); + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_CONTEXT_TYPE: + var context = type; + return getContextName(context) + ".Consumer"; - if (frame !== undefined) { - return frame; - } - } - - var control; - reentry = true; - var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. - - Error.prepareStackTrace = undefined; - var previousDispatcher; - - { - previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function - // for warnings. - - ReactCurrentDispatcher.current = null; - disableLogs(); - } - - try { - // This should throw. - if (construct) { - // Something should be setting the props in the constructor. - var Fake = function () { - throw Error(); - }; // $FlowFixMe[prop-missing] - - Object.defineProperty(Fake.prototype, "props", { - set: function () { - // We use a throwing setter instead of frozen or non-writable props - // because that won't throw in a non-strict mode function. - throw Error(); - } - }); + case REACT_PROVIDER_TYPE: + var provider = type; + return getContextName(provider._context) + ".Provider"; - if (typeof Reflect === "object" && Reflect.construct) { - // We construct a different control for this case to include any extra - // frames added by the construct call. - try { - Reflect.construct(Fake, []); - } catch (x) { - control = x; - } + case REACT_FORWARD_REF_TYPE: + return getWrappedName(type, type.render, "ForwardRef"); - Reflect.construct(fn, [], Fake); - } else { - try { - Fake.call(); - } catch (x) { - control = x; - } // $FlowFixMe[prop-missing] found when upgrading Flow + case REACT_MEMO_TYPE: + var outerName = type.displayName || null; - fn.call(Fake.prototype); - } - } else { - try { - throw Error(); - } catch (x) { - control = x; - } // TODO(luna): This will currently only throw if the function component - // tries to access React/ReactDOM/props. We should probably make this throw - // in simple components too - - var maybePromise = fn(); // If the function component returns a promise, it's likely an async - // component, which we don't yet support. Attach a noop catch handler to - // silence the error. - // TODO: Implement component stacks for async client components? - - if (maybePromise && typeof maybePromise.catch === "function") { - maybePromise.catch(function () {}); - } - } - } catch (sample) { - // This is inlined manually because closure doesn't do it for us. - if (sample && control && typeof sample.stack === "string") { - // This extracts the first frame from the sample that isn't also in the control. - // Skipping one frame that we assume is the frame that calls the two. - var sampleLines = sample.stack.split("\n"); - var controlLines = control.stack.split("\n"); - var s = sampleLines.length - 1; - var c = controlLines.length - 1; - - while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { - // We expect at least one stack frame to be shared. - // Typically this will be the root most one. However, stack frames may be - // cut off due to maximum stack limits. In this case, one maybe cut off - // earlier than the other. We assume that the sample is longer or the same - // and there for cut off earlier. So we should find the root most frame in - // the sample somewhere in the control. - c--; - } + if (outerName !== null) { + return outerName; + } - for (; s >= 1 && c >= 0; s--, c--) { - // Next we find the first one that isn't the same which should be the - // frame that called our sample function and the control. - if (sampleLines[s] !== controlLines[c]) { - // In V8, the first line is describing the message but other VMs don't. - // If we're about to return the first line, and the control is also on the same - // line, that's a pretty good indicator that our sample threw at same line as - // the control. I.e. before we entered the sample frame. So we ignore this result. - // This can happen if you passed a class to function component, or non-function. - if (s !== 1 || c !== 1) { - do { - s--; - c--; // We may still have similar intermediate frames from the construct call. - // The next one that isn't the same should be our match though. - - if (c < 0 || sampleLines[s] !== controlLines[c]) { - // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. - var _frame = "\n" + sampleLines[s].replace(" at new ", " at "); // If our component frame is labeled "" - // but we have a user-provided "displayName" - // splice it in to make the stack more readable. - - if (fn.displayName && _frame.includes("")) { - _frame = _frame.replace("", fn.displayName); - } + return getComponentNameFromType(type.type) || "Memo"; - { - if (typeof fn === "function") { - componentFrameCache.set(fn, _frame); - } - } // Return the line we found. + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - return _frame; - } - } while (s >= 1 && c >= 0); + try { + return getComponentNameFromType(init(payload)); + } catch (x) { + return null; + } } - - break; } } - } - } finally { - reentry = false; - { - ReactCurrentDispatcher.current = previousDispatcher; - reenableLogs(); + return null; } - Error.prepareStackTrace = previousPrepareStackTrace; - } // Fallback to just using the name if we couldn't make it throw. + var assign = Object.assign; + + // Helpers to patch console.logs to avoid logging during side-effect free + // replaying on render function. This currently only patches the object + // lazily which won't cover if the log function was extracted eagerly. + // We could also eagerly patch the method. + var disabledDepth = 0; + var prevLog; + var prevInfo; + var prevWarn; + var prevError; + var prevGroup; + var prevGroupCollapsed; + var prevGroupEnd; + + function disabledLog() {} + + disabledLog.__reactDisabledLog = true; + function disableLogs() { + { + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + prevLog = console.log; + prevInfo = console.info; + prevWarn = console.warn; + prevError = console.error; + prevGroup = console.group; + prevGroupCollapsed = console.groupCollapsed; + prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 + + var props = { + configurable: true, + enumerable: true, + value: disabledLog, + writable: true + }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. + + Object.defineProperties(console, { + info: props, + log: props, + warn: props, + error: props, + group: props, + groupCollapsed: props, + groupEnd: props + }); + /* eslint-enable react-internal/no-production-logging */ + } - var name = fn ? fn.displayName || fn.name : ""; - var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ""; + disabledDepth++; + } + } + function reenableLogs() { + { + disabledDepth--; + + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + var props = { + configurable: true, + enumerable: true, + writable: true + }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. + + Object.defineProperties(console, { + log: assign({}, props, { + value: prevLog + }), + info: assign({}, props, { + value: prevInfo + }), + warn: assign({}, props, { + value: prevWarn + }), + error: assign({}, props, { + value: prevError + }), + group: assign({}, props, { + value: prevGroup + }), + groupCollapsed: assign({}, props, { + value: prevGroupCollapsed + }), + groupEnd: assign({}, props, { + value: prevGroupEnd + }) + }); + /* eslint-enable react-internal/no-production-logging */ + } - { - if (typeof fn === "function") { - componentFrameCache.set(fn, syntheticFrame); + if (disabledDepth < 0) { + error( + "disabledDepth fell below zero. " + + "This is a bug in React. Please file an issue." + ); + } + } } - } - return syntheticFrame; -} -function describeFunctionComponentFrame(fn, source, ownerFn) { - { - return describeNativeComponentFrame(fn, false); - } -} + var ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; -function shouldConstruct(Component) { - var prototype = Component.prototype; - return !!(prototype && prototype.isReactComponent); -} + var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; + var prefix; + function describeBuiltInComponentFrame(name, source, ownerFn) { + { + if (prefix === undefined) { + // Extract the VM specific prefix used by each line. + try { + throw Error(); + } catch (x) { + var match = x.stack.trim().match(/\n( *(at )?)/); + prefix = (match && match[1]) || ""; + } + } // We use the prefix to ensure our stacks line up with native stack frames. -function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { - if (type == null) { - return ""; - } + return "\n" + prefix + name; + } + } + var reentry = false; + var componentFrameCache; - if (typeof type === "function") { { - return describeNativeComponentFrame(type, shouldConstruct(type)); + var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; + componentFrameCache = new PossiblyWeakMap(); } - } - if (typeof type === "string") { - return describeBuiltInComponentFrame(type); - } + function describeNativeComponentFrame(fn, construct) { + // If something asked for a stack inside a fake render, it should get ignored. + if (!fn || reentry) { + return ""; + } - switch (type) { - case REACT_SUSPENSE_TYPE: - return describeBuiltInComponentFrame("Suspense"); + { + var frame = componentFrameCache.get(fn); - case REACT_SUSPENSE_LIST_TYPE: - return describeBuiltInComponentFrame("SuspenseList"); - } + if (frame !== undefined) { + return frame; + } + } - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_FORWARD_REF_TYPE: - return describeFunctionComponentFrame(type.render); + var control; + reentry = true; + var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. - case REACT_MEMO_TYPE: - // Memo may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); + Error.prepareStackTrace = undefined; + var previousDispatcher; - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + { + previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function + // for warnings. - try { - // Lazy may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV( - init(payload), - source, - ownerFn - ); - } catch (x) {} + ReactCurrentDispatcher.current = null; + disableLogs(); } - } - } - - return ""; -} -// $FlowFixMe[method-unbinding] -var hasOwnProperty = Object.prototype.hasOwnProperty; - -var loggedTypeFailures = {}; -var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; - -function setCurrentlyValidatingElement$1(element) { - { - if (element) { - var owner = element._owner; - var stack = describeUnknownElementTypeFrameInDEV( - element.type, - element._source, - owner ? owner.type : null - ); - ReactDebugCurrentFrame$1.setExtraStackFrame(stack); - } else { - ReactDebugCurrentFrame$1.setExtraStackFrame(null); - } - } -} - -function checkPropTypes(typeSpecs, values, location, componentName, element) { - { - // $FlowFixMe[incompatible-use] This is okay but Flow doesn't know it. - var has = Function.call.bind(hasOwnProperty); + try { + // This should throw. + if (construct) { + // Something should be setting the props in the constructor. + var Fake = function () { + throw Error(); + }; // $FlowFixMe[prop-missing] + + Object.defineProperty(Fake.prototype, "props", { + set: function () { + // We use a throwing setter instead of frozen or non-writable props + // because that won't throw in a non-strict mode function. + throw Error(); + } + }); + + if (typeof Reflect === "object" && Reflect.construct) { + // We construct a different control for this case to include any extra + // frames added by the construct call. + try { + Reflect.construct(Fake, []); + } catch (x) { + control = x; + } - for (var typeSpecName in typeSpecs) { - if (has(typeSpecs, typeSpecName)) { - var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to - // fail the render phase where it didn't fail before. So we log it. - // After these have been cleaned up, we'll let them throw. + Reflect.construct(fn, [], Fake); + } else { + try { + Fake.call(); + } catch (x) { + control = x; + } // $FlowFixMe[prop-missing] found when upgrading Flow - try { - // This is intentionally an invariant that gets caught. It's the same - // behavior as without this statement except with a better message. - if (typeof typeSpecs[typeSpecName] !== "function") { - // eslint-disable-next-line react-internal/prod-error-codes - 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`." - ); - err.name = "Invariant Violation"; - throw err; + fn.call(Fake.prototype); + } + } else { + try { + throw Error(); + } catch (x) { + control = x; + } // TODO(luna): This will currently only throw if the function component + // tries to access React/ReactDOM/props. We should probably make this throw + // in simple components too + + var maybePromise = fn(); // If the function component returns a promise, it's likely an async + // component, which we don't yet support. Attach a noop catch handler to + // silence the error. + // TODO: Implement component stacks for async client components? + + if (maybePromise && typeof maybePromise.catch === "function") { + maybePromise.catch(function () {}); } - - error$1 = typeSpecs[typeSpecName]( - values, - typeSpecName, - componentName, - location, - null, - "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" - ); - } catch (ex) { - error$1 = ex; } + } catch (sample) { + // This is inlined manually because closure doesn't do it for us. + if (sample && control && typeof sample.stack === "string") { + // This extracts the first frame from the sample that isn't also in the control. + // Skipping one frame that we assume is the frame that calls the two. + var sampleLines = sample.stack.split("\n"); + var controlLines = control.stack.split("\n"); + var s = sampleLines.length - 1; + var c = controlLines.length - 1; + + while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { + // We expect at least one stack frame to be shared. + // Typically this will be the root most one. However, stack frames may be + // cut off due to maximum stack limits. In this case, one maybe cut off + // earlier than the other. We assume that the sample is longer or the same + // and there for cut off earlier. So we should find the root most frame in + // the sample somewhere in the control. + c--; + } - if (error$1 && !(error$1 instanceof Error)) { - setCurrentlyValidatingElement$1(element); + for (; s >= 1 && c >= 0; s--, c--) { + // Next we find the first one that isn't the same which should be the + // frame that called our sample function and the control. + if (sampleLines[s] !== controlLines[c]) { + // In V8, the first line is describing the message but other VMs don't. + // If we're about to return the first line, and the control is also on the same + // line, that's a pretty good indicator that our sample threw at same line as + // the control. I.e. before we entered the sample frame. So we ignore this result. + // This can happen if you passed a class to function component, or non-function. + if (s !== 1 || c !== 1) { + do { + s--; + c--; // We may still have similar intermediate frames from the construct call. + // The next one that isn't the same should be our match though. + + if (c < 0 || sampleLines[s] !== controlLines[c]) { + // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. + var _frame = + "\n" + sampleLines[s].replace(" at new ", " at "); // If our component frame is labeled "" + // but we have a user-provided "displayName" + // splice it in to make the stack more readable. + + if (fn.displayName && _frame.includes("")) { + _frame = _frame.replace("", fn.displayName); + } + + { + if (typeof fn === "function") { + componentFrameCache.set(fn, _frame); + } + } // Return the line we found. + + return _frame; + } + } while (s >= 1 && c >= 0); + } - 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 - ); + break; + } + } + } + } finally { + reentry = false; - setCurrentlyValidatingElement$1(null); + { + ReactCurrentDispatcher.current = previousDispatcher; + reenableLogs(); } - if ( - error$1 instanceof Error && - !(error$1.message in loggedTypeFailures) - ) { - // Only monitor this failure once because there tends to be a lot of the - // same error. - loggedTypeFailures[error$1.message] = true; - setCurrentlyValidatingElement$1(element); + Error.prepareStackTrace = previousPrepareStackTrace; + } // Fallback to just using the name if we couldn't make it throw. - error("Failed %s type: %s", location, error$1.message); + var name = fn ? fn.displayName || fn.name : ""; + var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ""; - setCurrentlyValidatingElement$1(null); + { + if (typeof fn === "function") { + componentFrameCache.set(fn, syntheticFrame); } } + + return syntheticFrame; + } + function describeFunctionComponentFrame(fn, source, ownerFn) { + { + return describeNativeComponentFrame(fn, false); + } } - } -} -var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare + function shouldConstruct(Component) { + var prototype = Component.prototype; + return !!(prototype && prototype.isReactComponent); + } -function isArray(a) { - return isArrayImpl(a); -} + function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { + if (type == null) { + return ""; + } -/* - * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol - * and Temporal.* types. See https://github.com/facebook/react/pull/22064. - * - * The functions in this module will throw an easier-to-understand, - * easier-to-debug exception with a clear errors message message explaining the - * problem. (Instead of a confusing exception thrown inside the implementation - * of the `value` object). - */ -// $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. -function typeName(value) { - { - // toStringTag is needed for namespaced types like Temporal.Instant - var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; - var type = - (hasToStringTag && value[Symbol.toStringTag]) || - value.constructor.name || - "Object"; // $FlowFixMe[incompatible-return] - - return type; - } -} // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - -function willCoercionThrow(value) { - { - try { - testStringCoercion(value); - return false; - } catch (e) { - return true; - } - } -} + if (typeof type === "function") { + { + return describeNativeComponentFrame(type, shouldConstruct(type)); + } + } -function testStringCoercion(value) { - // If you ended up here by following an exception call stack, here's what's - // happened: you supplied an object or symbol value to React (as a prop, key, - // DOM attribute, CSS property, string ref, etc.) and when React tried to - // coerce it to a string using `'' + value`, an exception was thrown. - // - // The most common types that will cause this exception are `Symbol` instances - // and Temporal objects like `Temporal.Instant`. But any object that has a - // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this - // exception. (Library authors do this to prevent users from using built-in - // numeric operators like `+` or comparison operators like `>=` because custom - // methods are needed to perform accurate arithmetic or comparison.) - // - // To fix the problem, coerce this object or symbol value to a string before - // passing it to React. The most reliable way is usually `String(value)`. - // - // To find which value is throwing, check the browser or debugger console. - // Before this exception was thrown, there should be `console.error` output - // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the - // problem and how that type was used: key, atrribute, input value prop, etc. - // In most cases, this console output also shows the component and its - // ancestor components where the exception happened. - // - // eslint-disable-next-line react-internal/safe-string-coercion - return "" + value; -} -function checkKeyStringCoercion(value) { - { - if (willCoercionThrow(value)) { - error( - "The provided key is an unsupported type %s." + - " This value must be coerced to a string before using it here.", - typeName(value) - ); - - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) - } - } -} + if (typeof type === "string") { + return describeBuiltInComponentFrame(type); + } -var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; -var RESERVED_PROPS = { - key: true, - ref: true, - __self: true, - __source: true -}; -var specialPropKeyWarningShown; -var specialPropRefWarningShown; -var didWarnAboutStringRefs; - -{ - didWarnAboutStringRefs = {}; -} + switch (type) { + case REACT_SUSPENSE_TYPE: + return describeBuiltInComponentFrame("Suspense"); -function hasValidRef(config) { - { - if (hasOwnProperty.call(config, "ref")) { - var getter = Object.getOwnPropertyDescriptor(config, "ref").get; + case REACT_SUSPENSE_LIST_TYPE: + return describeBuiltInComponentFrame("SuspenseList"); + } - if (getter && getter.isReactWarning) { - return false; + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_FORWARD_REF_TYPE: + return describeFunctionComponentFrame(type.render); + + case REACT_MEMO_TYPE: + // Memo may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + type.type, + source, + ownerFn + ); + + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; + + try { + // Lazy may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + init(payload), + source, + ownerFn + ); + } catch (x) {} + } + } } + + return ""; } - } - return config.ref !== undefined; -} + // $FlowFixMe[method-unbinding] + var hasOwnProperty = Object.prototype.hasOwnProperty; -function hasValidKey(config) { - { - if (hasOwnProperty.call(config, "key")) { - var getter = Object.getOwnPropertyDescriptor(config, "key").get; + var loggedTypeFailures = {}; + var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; - if (getter && getter.isReactWarning) { - return false; + function setCurrentlyValidatingElement$1(element) { + { + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV( + element.type, + element._source, + owner ? owner.type : null + ); + ReactDebugCurrentFrame$1.setExtraStackFrame(stack); + } else { + ReactDebugCurrentFrame$1.setExtraStackFrame(null); + } } } - } - return config.key !== undefined; -} - -function warnIfStringRefCannotBeAutoConverted(config, self) { - { - if ( - typeof config.ref === "string" && - ReactCurrentOwner$1.current && - self && - ReactCurrentOwner$1.current.stateNode !== self + function checkPropTypes( + typeSpecs, + values, + location, + componentName, + element ) { - var componentName = getComponentNameFromType( - ReactCurrentOwner$1.current.type - ); + { + // $FlowFixMe[incompatible-use] This is okay but Flow doesn't know it. + var has = Function.call.bind(hasOwnProperty); + + for (var typeSpecName in typeSpecs) { + if (has(typeSpecs, typeSpecName)) { + var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to + // fail the render phase where it didn't fail before. So we log it. + // After these have been cleaned up, we'll let them throw. + + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + if (typeof typeSpecs[typeSpecName] !== "function") { + // eslint-disable-next-line react-internal/prod-error-codes + 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`." + ); + err.name = "Invariant Violation"; + throw err; + } - if (!didWarnAboutStringRefs[componentName]) { - error( - 'Component "%s" contains the string ref "%s". ' + - "Support for string refs will be removed in a future major release. " + - "This case cannot be automatically converted to an arrow function. " + - "We ask you to manually fix this case by using useRef() or createRef() instead. " + - "Learn more about using refs safely here: " + - "https://reactjs.org/link/strict-mode-string-ref", - getComponentNameFromType(ReactCurrentOwner$1.current.type), - config.ref - ); + error$1 = typeSpecs[typeSpecName]( + values, + typeSpecName, + componentName, + location, + null, + "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" + ); + } catch (ex) { + error$1 = ex; + } - didWarnAboutStringRefs[componentName] = true; - } - } - } -} + if (error$1 && !(error$1 instanceof Error)) { + setCurrentlyValidatingElement$1(element); + + 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 + ); + + setCurrentlyValidatingElement$1(null); + } -function defineKeyPropWarningGetter(props, displayName) { - { - var warnAboutAccessingKey = function () { - if (!specialPropKeyWarningShown) { - specialPropKeyWarningShown = true; + if ( + error$1 instanceof Error && + !(error$1.message in loggedTypeFailures) + ) { + // Only monitor this failure once because there tends to be a lot of the + // same error. + loggedTypeFailures[error$1.message] = true; + setCurrentlyValidatingElement$1(element); - error( - "%s: `key` is not a prop. Trying to access it will result " + - "in `undefined` being returned. If you need to access the same " + - "value within the child component, you should pass it as a different " + - "prop. (https://reactjs.org/link/special-props)", - displayName - ); + error("Failed %s type: %s", location, error$1.message); + + setCurrentlyValidatingElement$1(null); + } + } + } } - }; + } - warnAboutAccessingKey.isReactWarning = true; - Object.defineProperty(props, "key", { - get: warnAboutAccessingKey, - configurable: true - }); - } -} + var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare -function defineRefPropWarningGetter(props, displayName) { - { - var warnAboutAccessingRef = function () { - if (!specialPropRefWarningShown) { - specialPropRefWarningShown = true; + function isArray(a) { + return isArrayImpl(a); + } - error( - "%s: `ref` is not a prop. Trying to access it will result " + - "in `undefined` being returned. If you need to access the same " + - "value within the child component, you should pass it as a different " + - "prop. (https://reactjs.org/link/special-props)", - displayName - ); + /* + * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol + * and Temporal.* types. See https://github.com/facebook/react/pull/22064. + * + * The functions in this module will throw an easier-to-understand, + * easier-to-debug exception with a clear errors message message explaining the + * problem. (Instead of a confusing exception thrown inside the implementation + * of the `value` object). + */ + // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. + function typeName(value) { + { + // toStringTag is needed for namespaced types like Temporal.Instant + var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; + var type = + (hasToStringTag && value[Symbol.toStringTag]) || + value.constructor.name || + "Object"; // $FlowFixMe[incompatible-return] + + return type; } - }; + } // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - warnAboutAccessingRef.isReactWarning = true; - Object.defineProperty(props, "ref", { - get: warnAboutAccessingRef, - configurable: true - }); - } -} -/** - * Factory method to create a new React element. This no longer adheres to - * the class pattern, so do not use new to call it. Also, instanceof check - * will not work. Instead test $$typeof field against Symbol.for('react.element') to check - * if something is a React Element. - * - * @param {*} type - * @param {*} props - * @param {*} key - * @param {string|object} ref - * @param {*} owner - * @param {*} self A *temporary* helper to detect places where `this` is - * different from the `owner` when React.createElement is called, so that we - * can warn. We want to get rid of owner and replace string `ref`s with arrow - * functions, and as long as `this` and owner are the same, there will be no - * change in behavior. - * @param {*} source An annotation object (added by a transpiler or otherwise) - * indicating filename, line number, and/or other information. - * @internal - */ + function willCoercionThrow(value) { + { + try { + testStringCoercion(value); + return false; + } catch (e) { + return true; + } + } + } -function ReactElement(type, key, ref, self, source, owner, props) { - var element = { - // This tag allows us to uniquely identify this as a React Element - $$typeof: REACT_ELEMENT_TYPE, - // Built-in properties that belong on the element - type: type, - key: key, - ref: ref, - props: props, - // Record the component responsible for creating this element. - _owner: owner - }; - - { - // The validation flag is currently mutative. We put it on - // an external backing store so that we can freeze the whole object. - // This can be replaced with a WeakMap once they are implemented in - // commonly used development environments. - element._store = {}; // To make comparing ReactElements easier for testing purposes, we make - // the validation flag non-enumerable (where possible, which should - // include every environment we run tests in), so the test framework - // ignores it. - - Object.defineProperty(element._store, "validated", { - configurable: false, - enumerable: false, - writable: true, - value: false - }); // self and source are DEV only properties. - - Object.defineProperty(element, "_self", { - configurable: false, - enumerable: false, - writable: false, - value: self - }); // Two elements created in two different places should be considered - // equal for testing purposes and therefore we hide it from enumeration. - - Object.defineProperty(element, "_source", { - configurable: false, - enumerable: false, - writable: false, - value: source - }); - - if (Object.freeze) { - Object.freeze(element.props); - Object.freeze(element); + function testStringCoercion(value) { + // If you ended up here by following an exception call stack, here's what's + // happened: you supplied an object or symbol value to React (as a prop, key, + // DOM attribute, CSS property, string ref, etc.) and when React tried to + // coerce it to a string using `'' + value`, an exception was thrown. + // + // The most common types that will cause this exception are `Symbol` instances + // and Temporal objects like `Temporal.Instant`. But any object that has a + // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this + // exception. (Library authors do this to prevent users from using built-in + // numeric operators like `+` or comparison operators like `>=` because custom + // methods are needed to perform accurate arithmetic or comparison.) + // + // To fix the problem, coerce this object or symbol value to a string before + // passing it to React. The most reliable way is usually `String(value)`. + // + // To find which value is throwing, check the browser or debugger console. + // Before this exception was thrown, there should be `console.error` output + // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the + // problem and how that type was used: key, atrribute, input value prop, etc. + // In most cases, this console output also shows the component and its + // ancestor components where the exception happened. + // + // eslint-disable-next-line react-internal/safe-string-coercion + return "" + value; } - } + function checkKeyStringCoercion(value) { + { + if (willCoercionThrow(value)) { + error( + "The provided key is an unsupported type %s." + + " This value must be coerced to a string before using it here.", + typeName(value) + ); - return element; -} -/** - * https://github.com/reactjs/rfcs/pull/107 - * @param {*} type - * @param {object} props - * @param {string} key - */ + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + } + } + } -function jsxDEV$1(type, config, maybeKey, source, self) { - { - var propName; // Reserved names are extracted + var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; + var RESERVED_PROPS = { + key: true, + ref: true, + __self: true, + __source: true + }; + var specialPropKeyWarningShown; + var specialPropRefWarningShown; + var didWarnAboutStringRefs; - var props = {}; - var key = null; - var ref = null; // Currently, key can be spread in as a prop. This causes a potential - // issue if key is also explicitly declared (ie.
- // or
). We want to deprecate key spread, - // but as an intermediary step, we will use jsxDEV for everything except - //
, because we aren't currently able to tell if - // key is explicitly declared to be undefined or not. + { + didWarnAboutStringRefs = {}; + } - if (maybeKey !== undefined) { + function hasValidRef(config) { { - checkKeyStringCoercion(maybeKey); + if (hasOwnProperty.call(config, "ref")) { + var getter = Object.getOwnPropertyDescriptor(config, "ref").get; + + if (getter && getter.isReactWarning) { + return false; + } + } } - key = "" + maybeKey; + return config.ref !== undefined; } - if (hasValidKey(config)) { + function hasValidKey(config) { { - checkKeyStringCoercion(config.key); + if (hasOwnProperty.call(config, "key")) { + var getter = Object.getOwnPropertyDescriptor(config, "key").get; + + if (getter && getter.isReactWarning) { + return false; + } + } } - key = "" + config.key; + return config.key !== undefined; } - if (hasValidRef(config)) { - ref = config.ref; - warnIfStringRefCannotBeAutoConverted(config, self); - } // Remaining properties are added to a new props object - - for (propName in config) { - if ( - hasOwnProperty.call(config, propName) && - !RESERVED_PROPS.hasOwnProperty(propName) - ) { - props[propName] = config[propName]; - } - } // Resolve default props + function warnIfStringRefCannotBeAutoConverted(config, self) { + { + if ( + typeof config.ref === "string" && + ReactCurrentOwner$1.current && + self && + ReactCurrentOwner$1.current.stateNode !== self + ) { + var componentName = getComponentNameFromType( + ReactCurrentOwner$1.current.type + ); - if (type && type.defaultProps) { - var defaultProps = type.defaultProps; + if (!didWarnAboutStringRefs[componentName]) { + error( + 'Component "%s" contains the string ref "%s". ' + + "Support for string refs will be removed in a future major release. " + + "This case cannot be automatically converted to an arrow function. " + + "We ask you to manually fix this case by using useRef() or createRef() instead. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-string-ref", + getComponentNameFromType(ReactCurrentOwner$1.current.type), + config.ref + ); - for (propName in defaultProps) { - if (props[propName] === undefined) { - props[propName] = defaultProps[propName]; + didWarnAboutStringRefs[componentName] = true; + } } } } - if (key || ref) { - var displayName = - typeof type === "function" - ? type.displayName || type.name || "Unknown" - : type; + function defineKeyPropWarningGetter(props, displayName) { + { + var warnAboutAccessingKey = function () { + if (!specialPropKeyWarningShown) { + specialPropKeyWarningShown = true; - if (key) { - defineKeyPropWarningGetter(props, displayName); - } + error( + "%s: `key` is not a prop. Trying to access it will result " + + "in `undefined` being returned. If you need to access the same " + + "value within the child component, you should pass it as a different " + + "prop. (https://reactjs.org/link/special-props)", + displayName + ); + } + }; - if (ref) { - defineRefPropWarningGetter(props, displayName); + warnAboutAccessingKey.isReactWarning = true; + Object.defineProperty(props, "key", { + get: warnAboutAccessingKey, + configurable: true + }); } } - return ReactElement( - type, - key, - ref, - self, - source, - ReactCurrentOwner$1.current, - props - ); - } -} + function defineRefPropWarningGetter(props, displayName) { + { + var warnAboutAccessingRef = function () { + if (!specialPropRefWarningShown) { + specialPropRefWarningShown = true; + + error( + "%s: `ref` is not a prop. Trying to access it will result " + + "in `undefined` being returned. If you need to access the same " + + "value within the child component, you should pass it as a different " + + "prop. (https://reactjs.org/link/special-props)", + displayName + ); + } + }; -var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; -var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; -var REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"); - -function setCurrentlyValidatingElement(element) { - { - if (element) { - var owner = element._owner; - var stack = describeUnknownElementTypeFrameInDEV( - element.type, - element._source, - owner ? owner.type : null - ); - ReactDebugCurrentFrame.setExtraStackFrame(stack); - } else { - ReactDebugCurrentFrame.setExtraStackFrame(null); + warnAboutAccessingRef.isReactWarning = true; + Object.defineProperty(props, "ref", { + get: warnAboutAccessingRef, + configurable: true + }); + } } - } -} + /** + * Factory method to create a new React element. This no longer adheres to + * the class pattern, so do not use new to call it. Also, instanceof check + * will not work. Instead test $$typeof field against Symbol.for('react.element') to check + * if something is a React Element. + * + * @param {*} type + * @param {*} props + * @param {*} key + * @param {string|object} ref + * @param {*} owner + * @param {*} self A *temporary* helper to detect places where `this` is + * different from the `owner` when React.createElement is called, so that we + * can warn. We want to get rid of owner and replace string `ref`s with arrow + * functions, and as long as `this` and owner are the same, there will be no + * change in behavior. + * @param {*} source An annotation object (added by a transpiler or otherwise) + * indicating filename, line number, and/or other information. + * @internal + */ + + function ReactElement(type, key, ref, self, source, owner, props) { + var element = { + // This tag allows us to uniquely identify this as a React Element + $$typeof: REACT_ELEMENT_TYPE, + // Built-in properties that belong on the element + type: type, + key: key, + ref: ref, + props: props, + // Record the component responsible for creating this element. + _owner: owner + }; -var propTypesMisspellWarningShown; + { + // The validation flag is currently mutative. We put it on + // an external backing store so that we can freeze the whole object. + // This can be replaced with a WeakMap once they are implemented in + // commonly used development environments. + element._store = {}; // To make comparing ReactElements easier for testing purposes, we make + // the validation flag non-enumerable (where possible, which should + // include every environment we run tests in), so the test framework + // ignores it. + + Object.defineProperty(element._store, "validated", { + configurable: false, + enumerable: false, + writable: true, + value: false + }); // self and source are DEV only properties. + + Object.defineProperty(element, "_self", { + configurable: false, + enumerable: false, + writable: false, + value: self + }); // Two elements created in two different places should be considered + // equal for testing purposes and therefore we hide it from enumeration. + + Object.defineProperty(element, "_source", { + configurable: false, + enumerable: false, + writable: false, + value: source + }); + + if (Object.freeze) { + Object.freeze(element.props); + Object.freeze(element); + } + } -{ - propTypesMisspellWarningShown = false; -} -/** - * Verifies the object is a ReactElement. - * See https://reactjs.org/docs/react-api.html#isvalidelement - * @param {?object} object - * @return {boolean} True if `object` is a ReactElement. - * @final - */ + return element; + } + /** + * https://github.com/reactjs/rfcs/pull/107 + * @param {*} type + * @param {object} props + * @param {string} key + */ + + function jsxDEV$1(type, config, maybeKey, source, self) { + { + var propName; // Reserved names are extracted + + var props = {}; + var key = null; + var ref = null; // Currently, key can be spread in as a prop. This causes a potential + // issue if key is also explicitly declared (ie.
+ // or
). We want to deprecate key spread, + // but as an intermediary step, we will use jsxDEV for everything except + //
, because we aren't currently able to tell if + // key is explicitly declared to be undefined or not. + + if (maybeKey !== undefined) { + { + checkKeyStringCoercion(maybeKey); + } -function isValidElement(object) { - { - return ( - typeof object === "object" && - object !== null && - object.$$typeof === REACT_ELEMENT_TYPE - ); - } -} + key = "" + maybeKey; + } -function getDeclarationErrorAddendum() { - { - if (ReactCurrentOwner.current) { - var name = getComponentNameFromType(ReactCurrentOwner.current.type); + if (hasValidKey(config)) { + { + checkKeyStringCoercion(config.key); + } - if (name) { - return "\n\nCheck the render method of `" + name + "`."; - } - } + key = "" + config.key; + } - return ""; - } -} + if (hasValidRef(config)) { + ref = config.ref; + warnIfStringRefCannotBeAutoConverted(config, self); + } // Remaining properties are added to a new props object + + for (propName in config) { + if ( + hasOwnProperty.call(config, propName) && + !RESERVED_PROPS.hasOwnProperty(propName) + ) { + props[propName] = config[propName]; + } + } // Resolve default props -function getSourceInfoErrorAddendum(source) { - { - if (source !== undefined) { - var fileName = source.fileName.replace(/^.*[\\\/]/, ""); - var lineNumber = source.lineNumber; - return "\n\nCheck your code at " + fileName + ":" + lineNumber + "."; - } + if (type && type.defaultProps) { + var defaultProps = type.defaultProps; - return ""; - } -} -/** - * Warn if there's no key explicitly set on dynamic arrays of children or - * object keys are not valid. This allows us to keep track of children between - * updates. - */ + for (propName in defaultProps) { + if (props[propName] === undefined) { + props[propName] = defaultProps[propName]; + } + } + } -var ownerHasKeyUseWarning = {}; + if (key || ref) { + var displayName = + typeof type === "function" + ? type.displayName || type.name || "Unknown" + : type; -function getCurrentComponentErrorInfo(parentType) { - { - var info = getDeclarationErrorAddendum(); + if (key) { + defineKeyPropWarningGetter(props, displayName); + } - if (!info) { - var parentName = - typeof parentType === "string" - ? parentType - : parentType.displayName || parentType.name; + if (ref) { + defineRefPropWarningGetter(props, displayName); + } + } - if (parentName) { - info = - "\n\nCheck the top-level render call using <" + parentName + ">."; + return ReactElement( + type, + key, + ref, + self, + source, + ReactCurrentOwner$1.current, + props + ); } } - return info; - } -} -/** - * Warn if the element doesn't have an explicit key assigned to it. - * This element is in an array. The array could grow and shrink or be - * reordered. All children that haven't already been validated are required to - * have a "key" property assigned to it. Error statuses are cached so a warning - * will only be shown once. - * - * @internal - * @param {ReactElement} element Element that requires a key. - * @param {*} parentType element's parent's type. - */ + var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + var REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"); -function validateExplicitKey(element, parentType) { - { - if (!element._store || element._store.validated || element.key != null) { - return; + function setCurrentlyValidatingElement(element) { + { + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV( + element.type, + element._source, + owner ? owner.type : null + ); + ReactDebugCurrentFrame.setExtraStackFrame(stack); + } else { + ReactDebugCurrentFrame.setExtraStackFrame(null); + } + } } - element._store.validated = true; - var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType); + var propTypesMisspellWarningShown; - if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { - return; + { + propTypesMisspellWarningShown = false; } - - ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a - // property, it may be the creator of the child that's responsible for - // assigning it a key. - - var childOwner = ""; - - if ( - element && - element._owner && - element._owner !== ReactCurrentOwner.current - ) { - // Give the component that originally created this child. - childOwner = - " It was passed a child from " + - getComponentNameFromType(element._owner.type) + - "."; + /** + * Verifies the object is a ReactElement. + * See https://reactjs.org/docs/react-api.html#isvalidelement + * @param {?object} object + * @return {boolean} True if `object` is a ReactElement. + * @final + */ + + function isValidElement(object) { + { + return ( + typeof object === "object" && + object !== null && + object.$$typeof === REACT_ELEMENT_TYPE + ); + } } - setCurrentlyValidatingElement(element); - - error( - 'Each child in a list should have a unique "key" prop.' + - "%s%s See https://reactjs.org/link/warning-keys for more information.", - currentComponentErrorInfo, - childOwner - ); + function getDeclarationErrorAddendum() { + { + if (ReactCurrentOwner.current) { + var name = getComponentNameFromType(ReactCurrentOwner.current.type); - setCurrentlyValidatingElement(null); - } -} -/** - * Ensure that every element either is passed in a static location, in an - * array with an explicit keys property defined, or in an object literal - * with valid key property. - * - * @internal - * @param {ReactNode} node Statically passed child of any type. - * @param {*} parentType node's parent's type. - */ + if (name) { + return "\n\nCheck the render method of `" + name + "`."; + } + } -function validateChildKeys(node, parentType) { - { - if (typeof node !== "object" || !node) { - return; + return ""; + } } - if (node.$$typeof === REACT_CLIENT_REFERENCE); - else if (isArray(node)) { - for (var i = 0; i < node.length; i++) { - var child = node[i]; - - if (isValidElement(child)) { - validateExplicitKey(child, parentType); - } - } - } else if (isValidElement(node)) { - // This element was passed in a valid location. - if (node._store) { - node._store.validated = true; - } - } else { - var iteratorFn = getIteratorFn(node); - - if (typeof iteratorFn === "function") { - // Entry iterators used to provide implicit keys, - // but now we print a separate warning for them later. - if (iteratorFn !== node.entries) { - var iterator = iteratorFn.call(node); - var step; - - while (!(step = iterator.next()).done) { - if (isValidElement(step.value)) { - validateExplicitKey(step.value, parentType); - } - } + function getSourceInfoErrorAddendum(source) { + { + if (source !== undefined) { + var fileName = source.fileName.replace(/^.*[\\\/]/, ""); + var lineNumber = source.lineNumber; + return "\n\nCheck your code at " + fileName + ":" + lineNumber + "."; } + + return ""; } } - } -} -/** - * Given an element, validate that its props follow the propTypes definition, - * provided by the type. - * - * @param {ReactElement} element - */ + /** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ -function validatePropTypes(element) { - { - var type = element.type; + var ownerHasKeyUseWarning = {}; - if (type === null || type === undefined || typeof type === "string") { - return; - } + function getCurrentComponentErrorInfo(parentType) { + { + var info = getDeclarationErrorAddendum(); - if (type.$$typeof === REACT_CLIENT_REFERENCE) { - return; - } + if (!info) { + var parentName = + typeof parentType === "string" + ? parentType + : parentType.displayName || parentType.name; - var propTypes; + if (parentName) { + info = + "\n\nCheck the top-level render call using <" + parentName + ">."; + } + } - if (typeof type === "function") { - propTypes = type.propTypes; - } else if ( - typeof type === "object" && - (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here. - // Inner props are checked in the reconciler. - type.$$typeof === REACT_MEMO_TYPE) - ) { - propTypes = type.propTypes; - } else { - return; + return info; + } } + /** + * Warn if the element doesn't have an explicit key assigned to it. + * This element is in an array. The array could grow and shrink or be + * reordered. All children that haven't already been validated are required to + * have a "key" property assigned to it. Error statuses are cached so a warning + * will only be shown once. + * + * @internal + * @param {ReactElement} element Element that requires a key. + * @param {*} parentType element's parent's type. + */ + + function validateExplicitKey(element, parentType) { + { + if ( + !element._store || + element._store.validated || + element.key != null + ) { + return; + } - if (propTypes) { - // Intentionally inside to avoid triggering lazy initializers: - var name = getComponentNameFromType(type); - checkPropTypes(propTypes, element.props, "prop", name, element); - } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) { - propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers: - - var _name = getComponentNameFromType(type); + element._store.validated = true; + var currentComponentErrorInfo = + getCurrentComponentErrorInfo(parentType); - error( - "Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?", - _name || "Unknown" - ); - } + if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { + return; + } - if ( - typeof type.getDefaultProps === "function" && - !type.getDefaultProps.isReactClassApproved - ) { - error( - "getDefaultProps is only used on classic React.createClass " + - "definitions. Use a static property named `defaultProps` instead." - ); - } - } -} -/** - * Given a fragment, validate that it can only be provided with fragment props - * @param {ReactElement} fragment - */ + ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a + // property, it may be the creator of the child that's responsible for + // assigning it a key. -function validateFragmentProps(fragment) { - { - var keys = Object.keys(fragment.props); + var childOwner = ""; - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; + if ( + element && + element._owner && + element._owner !== ReactCurrentOwner.current + ) { + // Give the component that originally created this child. + childOwner = + " It was passed a child from " + + getComponentNameFromType(element._owner.type) + + "."; + } - if (key !== "children" && key !== "key") { - setCurrentlyValidatingElement(fragment); + setCurrentlyValidatingElement(element); error( - "Invalid prop `%s` supplied to `React.Fragment`. " + - "React.Fragment can only have `key` and `children` props.", - key + 'Each child in a list should have a unique "key" prop.' + + "%s%s See https://reactjs.org/link/warning-keys for more information.", + currentComponentErrorInfo, + childOwner ); setCurrentlyValidatingElement(null); - break; } } + /** + * Ensure that every element either is passed in a static location, in an + * array with an explicit keys property defined, or in an object literal + * with valid key property. + * + * @internal + * @param {ReactNode} node Statically passed child of any type. + * @param {*} parentType node's parent's type. + */ + + function validateChildKeys(node, parentType) { + { + if (typeof node !== "object" || !node) { + return; + } - if (fragment.ref !== null) { - setCurrentlyValidatingElement(fragment); - - error("Invalid attribute `ref` supplied to `React.Fragment`."); + if (node.$$typeof === REACT_CLIENT_REFERENCE); + else if (isArray(node)) { + for (var i = 0; i < node.length; i++) { + var child = node[i]; - setCurrentlyValidatingElement(null); + if (isValidElement(child)) { + validateExplicitKey(child, parentType); + } + } + } else if (isValidElement(node)) { + // This element was passed in a valid location. + if (node._store) { + node._store.validated = true; + } + } else { + var iteratorFn = getIteratorFn(node); + + if (typeof iteratorFn === "function") { + // Entry iterators used to provide implicit keys, + // but now we print a separate warning for them later. + if (iteratorFn !== node.entries) { + var iterator = iteratorFn.call(node); + var step; + + while (!(step = iterator.next()).done) { + if (isValidElement(step.value)) { + validateExplicitKey(step.value, parentType); + } + } + } + } + } + } } - } -} + /** + * Given an element, validate that its props follow the propTypes definition, + * provided by the type. + * + * @param {ReactElement} element + */ + + function validatePropTypes(element) { + { + var type = element.type; -var didWarnAboutKeySpread = {}; -function jsxWithValidation(type, props, key, isStaticChildren, source, self) { - { - var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to - // succeed and there will likely be errors in render. + if (type === null || type === undefined || typeof type === "string") { + return; + } - if (!validType) { - var info = ""; + if (type.$$typeof === REACT_CLIENT_REFERENCE) { + return; + } - if ( - type === undefined || - (typeof type === "object" && - type !== null && - Object.keys(type).length === 0) - ) { - 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."; - } + var propTypes; - var sourceInfo = getSourceInfoErrorAddendum(source); + if (typeof type === "function") { + propTypes = type.propTypes; + } else if ( + typeof type === "object" && + (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here. + // Inner props are checked in the reconciler. + type.$$typeof === REACT_MEMO_TYPE) + ) { + propTypes = type.propTypes; + } else { + return; + } - if (sourceInfo) { - info += sourceInfo; - } else { - info += getDeclarationErrorAddendum(); - } + if (propTypes) { + // Intentionally inside to avoid triggering lazy initializers: + var name = getComponentNameFromType(type); + checkPropTypes(propTypes, element.props, "prop", name, element); + } else if ( + type.PropTypes !== undefined && + !propTypesMisspellWarningShown + ) { + propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers: - var typeString; - - if (type === null) { - typeString = "null"; - } else if (isArray(type)) { - typeString = "array"; - } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) { - typeString = - "<" + (getComponentNameFromType(type.type) || "Unknown") + " />"; - info = - " Did you accidentally export a JSX literal instead of a component?"; - } else { - typeString = typeof type; - } + var _name = getComponentNameFromType(type); + + error( + "Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?", + _name || "Unknown" + ); + } - error( - "React.jsx: type is invalid -- expected a string (for " + - "built-in components) or a class/function (for composite " + - "components) but got: %s.%s", - typeString, - info - ); + if ( + typeof type.getDefaultProps === "function" && + !type.getDefaultProps.isReactClassApproved + ) { + error( + "getDefaultProps is only used on classic React.createClass " + + "definitions. Use a static property named `defaultProps` instead." + ); + } + } } + /** + * Given a fragment, validate that it can only be provided with fragment props + * @param {ReactElement} fragment + */ - var element = jsxDEV$1(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used. - // TODO: Drop this when these are no longer allowed as the type argument. + function validateFragmentProps(fragment) { + { + var keys = Object.keys(fragment.props); - if (element == null) { - return element; - } // Skip key warning if the type isn't valid since our key validation logic - // doesn't expect a non-string/function type and can throw confusing errors. - // We don't want exception behavior to differ between dev and prod. - // (Rendering will throw with a helpful message and as soon as the type is - // fixed, the key warnings will appear.) - - if (validType) { - var children = props.children; - - if (children !== undefined) { - if (isStaticChildren) { - if (isArray(children)) { - for (var i = 0; i < children.length; i++) { - validateChildKeys(children[i], type); - } + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + + if (key !== "children" && key !== "key") { + setCurrentlyValidatingElement(fragment); - if (Object.freeze) { - Object.freeze(children); - } - } else { error( - "React.jsx: Static children should always be an array. " + - "You are likely explicitly calling React.jsxs or React.jsxDEV. " + - "Use the Babel transform instead." + "Invalid prop `%s` supplied to `React.Fragment`. " + + "React.Fragment can only have `key` and `children` props.", + key ); + + setCurrentlyValidatingElement(null); + break; } - } else { - validateChildKeys(children, type); + } + + if (fragment.ref !== null) { + setCurrentlyValidatingElement(fragment); + + error("Invalid attribute `ref` supplied to `React.Fragment`."); + + setCurrentlyValidatingElement(null); } } } - if (hasOwnProperty.call(props, "key")) { - var componentName = getComponentNameFromType(type); - var keys = Object.keys(props).filter(function (k) { - return k !== "key"; - }); - var beforeExample = - keys.length > 0 - ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" - : "{key: someKey}"; + var didWarnAboutKeySpread = {}; + function jsxWithValidation( + type, + props, + key, + isStaticChildren, + source, + self + ) { + { + var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to + // succeed and there will likely be errors in render. + + if (!validType) { + var info = ""; + + if ( + type === undefined || + (typeof type === "object" && + type !== null && + Object.keys(type).length === 0) + ) { + 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."; + } - if (!didWarnAboutKeySpread[componentName + beforeExample]) { - var afterExample = - keys.length > 0 ? "{" + keys.join(": ..., ") + ": ...}" : "{}"; + var sourceInfo = getSourceInfoErrorAddendum(source); - error( - 'A props object containing a "key" prop is being spread into JSX:\n' + - " let props = %s;\n" + - " <%s {...props} />\n" + - "React keys must be passed directly to JSX without using spread:\n" + - " let props = %s;\n" + - " <%s key={someKey} {...props} />", - beforeExample, - componentName, - afterExample, - componentName - ); + if (sourceInfo) { + info += sourceInfo; + } else { + info += getDeclarationErrorAddendum(); + } - didWarnAboutKeySpread[componentName + beforeExample] = true; - } - } + var typeString; + + if (type === null) { + typeString = "null"; + } else if (isArray(type)) { + typeString = "array"; + } else if ( + type !== undefined && + type.$$typeof === REACT_ELEMENT_TYPE + ) { + typeString = + "<" + (getComponentNameFromType(type.type) || "Unknown") + " />"; + info = + " Did you accidentally export a JSX literal instead of a component?"; + } else { + typeString = typeof type; + } - if (type === REACT_FRAGMENT_TYPE) { - validateFragmentProps(element); - } else { - validatePropTypes(element); - } + error( + "React.jsx: type is invalid -- expected a string (for " + + "built-in components) or a class/function (for composite " + + "components) but got: %s.%s", + typeString, + info + ); + } - return element; - } -} // These two functions exist to still get child warnings in dev + var element = jsxDEV$1(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used. + // TODO: Drop this when these are no longer allowed as the type argument. + + if (element == null) { + return element; + } // Skip key warning if the type isn't valid since our key validation logic + // doesn't expect a non-string/function type and can throw confusing errors. + // We don't want exception behavior to differ between dev and prod. + // (Rendering will throw with a helpful message and as soon as the type is + // fixed, the key warnings will appear.) + + if (validType) { + var children = props.children; + + if (children !== undefined) { + if (isStaticChildren) { + if (isArray(children)) { + for (var i = 0; i < children.length; i++) { + validateChildKeys(children[i], type); + } + + if (Object.freeze) { + Object.freeze(children); + } + } else { + error( + "React.jsx: Static children should always be an array. " + + "You are likely explicitly calling React.jsxs or React.jsxDEV. " + + "Use the Babel transform instead." + ); + } + } else { + validateChildKeys(children, type); + } + } + } -var jsxDEV = jsxWithValidation; + if (hasOwnProperty.call(props, "key")) { + var componentName = getComponentNameFromType(type); + var keys = Object.keys(props).filter(function (k) { + return k !== "key"; + }); + var beforeExample = + keys.length > 0 + ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" + : "{key: someKey}"; + + if (!didWarnAboutKeySpread[componentName + beforeExample]) { + var afterExample = + keys.length > 0 ? "{" + keys.join(": ..., ") + ": ...}" : "{}"; + + error( + 'A props object containing a "key" prop is being spread into JSX:\n' + + " let props = %s;\n" + + " <%s {...props} />\n" + + "React keys must be passed directly to JSX without using spread:\n" + + " let props = %s;\n" + + " <%s key={someKey} {...props} />", + beforeExample, + componentName, + afterExample, + componentName + ); + + didWarnAboutKeySpread[componentName + beforeExample] = true; + } + } + + if (type === REACT_FRAGMENT_TYPE) { + validateFragmentProps(element); + } else { + validatePropTypes(element); + } + + return element; + } + } // These two functions exist to still get child warnings in dev -exports.Fragment = REACT_FRAGMENT_TYPE; -exports.jsxDEV = jsxDEV; + var jsxDEV = jsxWithValidation; + exports.Fragment = REACT_FRAGMENT_TYPE; + exports.jsxDEV = jsxDEV; })(); } diff --git a/compiled/facebook-www/JSXDEVRuntime-prod.classic.js b/compiled/facebook-www/JSXDEVRuntime-prod.classic.js index 887e7a3f8b700..2ec6255234a19 100644 --- a/compiled/facebook-www/JSXDEVRuntime-prod.classic.js +++ b/compiled/facebook-www/JSXDEVRuntime-prod.classic.js @@ -1,15 +1,15 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @noflow - * @nolint - * @preventMunge - * @preserve-invariant-messages - */ +/* + Copyright (c) Meta Platforms, Inc. and affiliates. + + This source code is licensed under the MIT license found in the + LICENSE file in the root directory of this source tree. + + @noflow + @nolint + @preventMunge + @preserve-invariant-messages +*/ "use strict"; var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); require("ReactFeatureFlags"); diff --git a/compiled/facebook-www/JSXDEVRuntime-prod.modern.js b/compiled/facebook-www/JSXDEVRuntime-prod.modern.js index 887e7a3f8b700..2ec6255234a19 100644 --- a/compiled/facebook-www/JSXDEVRuntime-prod.modern.js +++ b/compiled/facebook-www/JSXDEVRuntime-prod.modern.js @@ -1,15 +1,15 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @noflow - * @nolint - * @preventMunge - * @preserve-invariant-messages - */ +/* + Copyright (c) Meta Platforms, Inc. and affiliates. + + This source code is licensed under the MIT license found in the + LICENSE file in the root directory of this source tree. + + @noflow + @nolint + @preventMunge + @preserve-invariant-messages +*/ "use strict"; var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); require("ReactFeatureFlags"); diff --git a/compiled/facebook-www/JSXDEVRuntime-profiling.classic.js b/compiled/facebook-www/JSXDEVRuntime-profiling.classic.js index 887e7a3f8b700..2ec6255234a19 100644 --- a/compiled/facebook-www/JSXDEVRuntime-profiling.classic.js +++ b/compiled/facebook-www/JSXDEVRuntime-profiling.classic.js @@ -1,15 +1,15 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @noflow - * @nolint - * @preventMunge - * @preserve-invariant-messages - */ +/* + Copyright (c) Meta Platforms, Inc. and affiliates. + + This source code is licensed under the MIT license found in the + LICENSE file in the root directory of this source tree. + + @noflow + @nolint + @preventMunge + @preserve-invariant-messages +*/ "use strict"; var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); require("ReactFeatureFlags"); diff --git a/compiled/facebook-www/JSXDEVRuntime-profiling.modern.js b/compiled/facebook-www/JSXDEVRuntime-profiling.modern.js index 887e7a3f8b700..2ec6255234a19 100644 --- a/compiled/facebook-www/JSXDEVRuntime-profiling.modern.js +++ b/compiled/facebook-www/JSXDEVRuntime-profiling.modern.js @@ -1,15 +1,15 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @noflow - * @nolint - * @preventMunge - * @preserve-invariant-messages - */ +/* + Copyright (c) Meta Platforms, Inc. and affiliates. + + This source code is licensed under the MIT license found in the + LICENSE file in the root directory of this source tree. + + @noflow + @nolint + @preventMunge + @preserve-invariant-messages +*/ "use strict"; var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); require("ReactFeatureFlags"); diff --git a/compiled/facebook-www/REVISION b/compiled/facebook-www/REVISION index e95993dd805b1..7edd11d59be1c 100644 --- a/compiled/facebook-www/REVISION +++ b/compiled/facebook-www/REVISION @@ -1 +1 @@ -2983249dd2bb1a295f27939e36ab0de9e4bfab76 +2c8a139a593e0294c3a6953d74b451bd05fdcfca diff --git a/compiled/facebook-www/React-dev.classic.js b/compiled/facebook-www/React-dev.classic.js index bb4645756d715..bb4e2cfd0ce87 100644 --- a/compiled/facebook-www/React-dev.classic.js +++ b/compiled/facebook-www/React-dev.classic.js @@ -1,4 +1,5 @@ /** + * @preserve * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the @@ -10,4113 +11,4163 @@ * @preserve-invariant-messages */ -'use strict'; +"use strict"; if (__DEV__) { - (function() { + (function () { + "use strict"; - 'use strict'; - -/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ -if ( - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart === - 'function' -) { - __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); -} - "use strict"; - -var ReactVersion = "18.3.0-www-classic-0b25f4fa"; - -// ATTENTION -// When adding new symbols to this file, -// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' -// The Symbol used to tag the ReactElement-like types. -var REACT_ELEMENT_TYPE = Symbol.for("react.element"); -var REACT_PORTAL_TYPE = Symbol.for("react.portal"); -var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); -var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); -var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); -var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); -var REACT_CONTEXT_TYPE = Symbol.for("react.context"); -var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); -var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); -var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); -var REACT_MEMO_TYPE = Symbol.for("react.memo"); -var REACT_LAZY_TYPE = Symbol.for("react.lazy"); -var REACT_SCOPE_TYPE = Symbol.for("react.scope"); -var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); -var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); -var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); -var REACT_CACHE_TYPE = Symbol.for("react.cache"); -var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); -var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; -var FAUX_ITERATOR_SYMBOL = "@@iterator"; -function getIteratorFn(maybeIterable) { - if (maybeIterable === null || typeof maybeIterable !== "object") { - return null; - } - - var maybeIterator = - (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || - maybeIterable[FAUX_ITERATOR_SYMBOL]; - - if (typeof maybeIterator === "function") { - return maybeIterator; - } - - return null; -} - -// This refers to a WWW module. -var warningWWW = require("warning"); -function warn(format) { - { - { - for ( - var _len = arguments.length, - args = new Array(_len > 1 ? _len - 1 : 0), - _key = 1; - _key < _len; - _key++ - ) { - args[_key - 1] = arguments[_key]; - } - - printWarning("warn", format, args); + /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ + if ( + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined" && + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart === + "function" + ) { + __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); } - } -} -function error(format) { - { - { - for ( - var _len2 = arguments.length, - args = new Array(_len2 > 1 ? _len2 - 1 : 0), - _key2 = 1; - _key2 < _len2; - _key2++ - ) { - args[_key2 - 1] = arguments[_key2]; + var ReactVersion = "18.3.0-www-classic-a3c149d0"; + + // ATTENTION + // When adding new symbols to this file, + // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' + // The Symbol used to tag the ReactElement-like types. + var REACT_ELEMENT_TYPE = Symbol.for("react.element"); + var REACT_PORTAL_TYPE = Symbol.for("react.portal"); + var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); + var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); + var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); + var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); + var REACT_CONTEXT_TYPE = Symbol.for("react.context"); + var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); + var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); + var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); + var REACT_MEMO_TYPE = Symbol.for("react.memo"); + var REACT_LAZY_TYPE = Symbol.for("react.lazy"); + var REACT_SCOPE_TYPE = Symbol.for("react.scope"); + var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); + var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); + var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); + var REACT_CACHE_TYPE = Symbol.for("react.cache"); + var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); + var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; + var FAUX_ITERATOR_SYMBOL = "@@iterator"; + function getIteratorFn(maybeIterable) { + if (maybeIterable === null || typeof maybeIterable !== "object") { + return null; } - printWarning("error", format, args); - } - } -} - -function printWarning(level, format, args) { - { - var React = require("react"); + var maybeIterator = + (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || + maybeIterable[FAUX_ITERATOR_SYMBOL]; - var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. - - if (ReactSharedInternals != null) { - var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - var stack = ReactDebugCurrentFrame.getStackAddendum(); - - if (stack !== "") { - format += "%s"; - args.push(stack); + if (typeof maybeIterator === "function") { + return maybeIterator; } - } // TODO: don't ignore level and pass it down somewhere too. - - args.unshift(format); - args.unshift(false); - warningWWW.apply(null, args); - } -} -var didWarnStateUpdateForUnmountedComponent = {}; + return null; + } -function warnNoop(publicInstance, callerName) { - { - var _constructor = publicInstance.constructor; - var componentName = - (_constructor && (_constructor.displayName || _constructor.name)) || - "ReactClass"; - var warningKey = componentName + "." + callerName; + // This refers to a WWW module. + var warningWWW = require("warning"); + function warn(format) { + { + { + for ( + var _len = arguments.length, + args = new Array(_len > 1 ? _len - 1 : 0), + _key = 1; + _key < _len; + _key++ + ) { + args[_key - 1] = arguments[_key]; + } - if (didWarnStateUpdateForUnmountedComponent[warningKey]) { - return; + printWarning("warn", format, args); + } + } } + function error(format) { + { + { + for ( + var _len2 = arguments.length, + args = new Array(_len2 > 1 ? _len2 - 1 : 0), + _key2 = 1; + _key2 < _len2; + _key2++ + ) { + args[_key2 - 1] = arguments[_key2]; + } - error( - "Can't call %s on a component that is not yet mounted. " + - "This is a no-op, but it might indicate a bug in your application. " + - "Instead, assign to `this.state` directly or define a `state = {};` " + - "class property with the desired state in the %s component.", - callerName, - componentName - ); - - didWarnStateUpdateForUnmountedComponent[warningKey] = true; - } -} -/** - * This is the abstract API for an update queue. - */ + printWarning("error", format, args); + } + } + } -var ReactNoopUpdateQueue = { - /** - * Checks whether or not this composite component is mounted. - * @param {ReactClass} publicInstance The instance we want to test. - * @return {boolean} True if mounted, false otherwise. - * @protected - * @final - */ - isMounted: function (publicInstance) { - return false; - }, - - /** - * Forces an update. This should only be invoked when it is known with - * certainty that we are **not** in a DOM transaction. - * - * You may want to call this when you know that some deeper aspect of the - * component's state has changed but `setState` was not called. - * - * This will not invoke `shouldComponentUpdate`, but it will invoke - * `componentWillUpdate` and `componentDidUpdate`. - * - * @param {ReactClass} publicInstance The instance that should rerender. - * @param {?function} callback Called after component is updated. - * @param {?string} callerName name of the calling function in the public API. - * @internal - */ - enqueueForceUpdate: function (publicInstance, callback, callerName) { - warnNoop(publicInstance, "forceUpdate"); - }, - - /** - * Replaces all of the state. Always use this or `setState` to mutate state. - * You should treat `this.state` as immutable. - * - * There is no guarantee that `this.state` will be immediately updated, so - * accessing `this.state` after calling this method may return the old value. - * - * @param {ReactClass} publicInstance The instance that should rerender. - * @param {object} completeState Next state. - * @param {?function} callback Called after component is updated. - * @param {?string} callerName name of the calling function in the public API. - * @internal - */ - enqueueReplaceState: function ( - publicInstance, - completeState, - callback, - callerName - ) { - warnNoop(publicInstance, "replaceState"); - }, - - /** - * Sets a subset of the state. This only exists because _pendingState is - * internal. This provides a merging strategy that is not available to deep - * properties which is confusing. TODO: Expose pendingState or don't use it - * during the merge. - * - * @param {ReactClass} publicInstance The instance that should rerender. - * @param {object} partialState Next partial state to be merged with state. - * @param {?function} callback Called after component is updated. - * @param {?string} Name of the calling function in the public API. - * @internal - */ - enqueueSetState: function ( - publicInstance, - partialState, - callback, - callerName - ) { - warnNoop(publicInstance, "setState"); - } -}; - -var assign = Object.assign; - -var emptyObject = {}; - -{ - Object.freeze(emptyObject); -} -/** - * Base class helpers for the updating state of a component. - */ + function printWarning(level, format, args) { + { + var React = require("react"); -function Component(props, context, updater) { - this.props = props; - this.context = context; // If a component has string refs, we will assign a different object later. + var ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. - this.refs = emptyObject; // We initialize the default updater but the real one gets injected by the - // renderer. + if (ReactSharedInternals != null) { + var ReactDebugCurrentFrame = + ReactSharedInternals.ReactDebugCurrentFrame; + var stack = ReactDebugCurrentFrame.getStackAddendum(); - this.updater = updater || ReactNoopUpdateQueue; -} + if (stack !== "") { + format += "%s"; + args.push(stack); + } + } // TODO: don't ignore level and pass it down somewhere too. -Component.prototype.isReactComponent = {}; -/** - * Sets a subset of the state. Always use this to mutate - * state. You should treat `this.state` as immutable. - * - * There is no guarantee that `this.state` will be immediately updated, so - * accessing `this.state` after calling this method may return the old value. - * - * There is no guarantee that calls to `setState` will run synchronously, - * as they may eventually be batched together. You can provide an optional - * callback that will be executed when the call to setState is actually - * completed. - * - * When a function is provided to setState, it will be called at some point in - * the future (not synchronously). It will be called with the up to date - * component arguments (state, props, context). These values can be different - * from this.* because your function may be called after receiveProps but before - * shouldComponentUpdate, and this new state, props, and context will not yet be - * assigned to this. - * - * @param {object|function} partialState Next partial state or function to - * produce next partial state to be merged with current state. - * @param {?function} callback Called after state is updated. - * @final - * @protected - */ + args.unshift(format); + args.unshift(false); + warningWWW.apply(null, args); + } + } -Component.prototype.setState = function (partialState, callback) { - if ( - typeof partialState !== "object" && - typeof partialState !== "function" && - partialState != null - ) { - throw new Error( - "setState(...): takes an object of state variables to update or a " + - "function which returns an object of state variables." - ); - } - - this.updater.enqueueSetState(this, partialState, callback, "setState"); -}; -/** - * Forces an update. This should only be invoked when it is known with - * certainty that we are **not** in a DOM transaction. - * - * You may want to call this when you know that some deeper aspect of the - * component's state has changed but `setState` was not called. - * - * This will not invoke `shouldComponentUpdate`, but it will invoke - * `componentWillUpdate` and `componentDidUpdate`. - * - * @param {?function} callback Called after update is complete. - * @final - * @protected - */ + var didWarnStateUpdateForUnmountedComponent = {}; -Component.prototype.forceUpdate = function (callback) { - this.updater.enqueueForceUpdate(this, callback, "forceUpdate"); -}; -/** - * Deprecated APIs. These APIs used to exist on classic React classes but since - * we would like to deprecate them, we're not going to move them over to this - * modern base class. Instead, we define a getter that warns if it's accessed. - */ + function warnNoop(publicInstance, callerName) { + { + var _constructor = publicInstance.constructor; + var componentName = + (_constructor && (_constructor.displayName || _constructor.name)) || + "ReactClass"; + var warningKey = componentName + "." + callerName; + + if (didWarnStateUpdateForUnmountedComponent[warningKey]) { + return; + } -{ - var deprecatedAPIs = { - isMounted: [ - "isMounted", - "Instead, make sure to clean up subscriptions and pending requests in " + - "componentWillUnmount to prevent memory leaks." - ], - replaceState: [ - "replaceState", - "Refactor your code to use setState instead (see " + - "https://github.com/facebook/react/issues/3236)." - ] - }; - - var defineDeprecationWarning = function (methodName, info) { - Object.defineProperty(Component.prototype, methodName, { - get: function () { - warn( - "%s(...) is deprecated in plain JavaScript React classes. %s", - info[0], - info[1] + error( + "Can't call %s on a component that is not yet mounted. " + + "This is a no-op, but it might indicate a bug in your application. " + + "Instead, assign to `this.state` directly or define a `state = {};` " + + "class property with the desired state in the %s component.", + callerName, + componentName ); - return undefined; + didWarnStateUpdateForUnmountedComponent[warningKey] = true; } - }); - }; - - for (var fnName in deprecatedAPIs) { - if (deprecatedAPIs.hasOwnProperty(fnName)) { - defineDeprecationWarning(fnName, deprecatedAPIs[fnName]); } - } -} + /** + * This is the abstract API for an update queue. + */ + + var ReactNoopUpdateQueue = { + /** + * Checks whether or not this composite component is mounted. + * @param {ReactClass} publicInstance The instance we want to test. + * @return {boolean} True if mounted, false otherwise. + * @protected + * @final + */ + isMounted: function (publicInstance) { + return false; + }, -function ComponentDummy() {} + /** + * Forces an update. This should only be invoked when it is known with + * certainty that we are **not** in a DOM transaction. + * + * You may want to call this when you know that some deeper aspect of the + * component's state has changed but `setState` was not called. + * + * This will not invoke `shouldComponentUpdate`, but it will invoke + * `componentWillUpdate` and `componentDidUpdate`. + * + * @param {ReactClass} publicInstance The instance that should rerender. + * @param {?function} callback Called after component is updated. + * @param {?string} callerName name of the calling function in the public API. + * @internal + */ + enqueueForceUpdate: function (publicInstance, callback, callerName) { + warnNoop(publicInstance, "forceUpdate"); + }, -ComponentDummy.prototype = Component.prototype; -/** - * Convenience component with default shallow equality check for sCU. - */ + /** + * Replaces all of the state. Always use this or `setState` to mutate state. + * You should treat `this.state` as immutable. + * + * There is no guarantee that `this.state` will be immediately updated, so + * accessing `this.state` after calling this method may return the old value. + * + * @param {ReactClass} publicInstance The instance that should rerender. + * @param {object} completeState Next state. + * @param {?function} callback Called after component is updated. + * @param {?string} callerName name of the calling function in the public API. + * @internal + */ + enqueueReplaceState: function ( + publicInstance, + completeState, + callback, + callerName + ) { + warnNoop(publicInstance, "replaceState"); + }, -function PureComponent(props, context, updater) { - this.props = props; - this.context = context; // If a component has string refs, we will assign a different object later. + /** + * Sets a subset of the state. This only exists because _pendingState is + * internal. This provides a merging strategy that is not available to deep + * properties which is confusing. TODO: Expose pendingState or don't use it + * during the merge. + * + * @param {ReactClass} publicInstance The instance that should rerender. + * @param {object} partialState Next partial state to be merged with state. + * @param {?function} callback Called after component is updated. + * @param {?string} Name of the calling function in the public API. + * @internal + */ + enqueueSetState: function ( + publicInstance, + partialState, + callback, + callerName + ) { + warnNoop(publicInstance, "setState"); + } + }; - this.refs = emptyObject; - this.updater = updater || ReactNoopUpdateQueue; -} + var assign = Object.assign; -var pureComponentPrototype = (PureComponent.prototype = new ComponentDummy()); -pureComponentPrototype.constructor = PureComponent; // Avoid an extra prototype jump for these methods. + var emptyObject = {}; -assign(pureComponentPrototype, Component.prototype); -pureComponentPrototype.isPureReactComponent = true; + { + Object.freeze(emptyObject); + } + /** + * Base class helpers for the updating state of a component. + */ -// an immutable object with a single mutable value -function createRef() { - var refObject = { - current: null - }; + function Component(props, context, updater) { + this.props = props; + this.context = context; // If a component has string refs, we will assign a different object later. - { - Object.seal(refObject); - } + this.refs = emptyObject; // We initialize the default updater but the real one gets injected by the + // renderer. - return refObject; -} + this.updater = updater || ReactNoopUpdateQueue; + } -var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare + Component.prototype.isReactComponent = {}; + /** + * Sets a subset of the state. Always use this to mutate + * state. You should treat `this.state` as immutable. + * + * There is no guarantee that `this.state` will be immediately updated, so + * accessing `this.state` after calling this method may return the old value. + * + * There is no guarantee that calls to `setState` will run synchronously, + * as they may eventually be batched together. You can provide an optional + * callback that will be executed when the call to setState is actually + * completed. + * + * When a function is provided to setState, it will be called at some point in + * the future (not synchronously). It will be called with the up to date + * component arguments (state, props, context). These values can be different + * from this.* because your function may be called after receiveProps but before + * shouldComponentUpdate, and this new state, props, and context will not yet be + * assigned to this. + * + * @param {object|function} partialState Next partial state or function to + * produce next partial state to be merged with current state. + * @param {?function} callback Called after state is updated. + * @final + * @protected + */ + + Component.prototype.setState = function (partialState, callback) { + if ( + typeof partialState !== "object" && + typeof partialState !== "function" && + partialState != null + ) { + throw new Error( + "setState(...): takes an object of state variables to update or a " + + "function which returns an object of state variables." + ); + } -function isArray(a) { - return isArrayImpl(a); -} + this.updater.enqueueSetState(this, partialState, callback, "setState"); + }; + /** + * Forces an update. This should only be invoked when it is known with + * certainty that we are **not** in a DOM transaction. + * + * You may want to call this when you know that some deeper aspect of the + * component's state has changed but `setState` was not called. + * + * This will not invoke `shouldComponentUpdate`, but it will invoke + * `componentWillUpdate` and `componentDidUpdate`. + * + * @param {?function} callback Called after update is complete. + * @final + * @protected + */ + + Component.prototype.forceUpdate = function (callback) { + this.updater.enqueueForceUpdate(this, callback, "forceUpdate"); + }; + /** + * Deprecated APIs. These APIs used to exist on classic React classes but since + * we would like to deprecate them, we're not going to move them over to this + * modern base class. Instead, we define a getter that warns if it's accessed. + */ -/* - * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol - * and Temporal.* types. See https://github.com/facebook/react/pull/22064. - * - * The functions in this module will throw an easier-to-understand, - * easier-to-debug exception with a clear errors message message explaining the - * problem. (Instead of a confusing exception thrown inside the implementation - * of the `value` object). - */ -// $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. -function typeName(value) { - { - // toStringTag is needed for namespaced types like Temporal.Instant - var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; - var type = - (hasToStringTag && value[Symbol.toStringTag]) || - value.constructor.name || - "Object"; // $FlowFixMe[incompatible-return] - - return type; - } -} // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - -function willCoercionThrow(value) { - { - try { - testStringCoercion(value); - return false; - } catch (e) { - return true; - } - } -} + { + var deprecatedAPIs = { + isMounted: [ + "isMounted", + "Instead, make sure to clean up subscriptions and pending requests in " + + "componentWillUnmount to prevent memory leaks." + ], + replaceState: [ + "replaceState", + "Refactor your code to use setState instead (see " + + "https://github.com/facebook/react/issues/3236)." + ] + }; -function testStringCoercion(value) { - // If you ended up here by following an exception call stack, here's what's - // happened: you supplied an object or symbol value to React (as a prop, key, - // DOM attribute, CSS property, string ref, etc.) and when React tried to - // coerce it to a string using `'' + value`, an exception was thrown. - // - // The most common types that will cause this exception are `Symbol` instances - // and Temporal objects like `Temporal.Instant`. But any object that has a - // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this - // exception. (Library authors do this to prevent users from using built-in - // numeric operators like `+` or comparison operators like `>=` because custom - // methods are needed to perform accurate arithmetic or comparison.) - // - // To fix the problem, coerce this object or symbol value to a string before - // passing it to React. The most reliable way is usually `String(value)`. - // - // To find which value is throwing, check the browser or debugger console. - // Before this exception was thrown, there should be `console.error` output - // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the - // problem and how that type was used: key, atrribute, input value prop, etc. - // In most cases, this console output also shows the component and its - // ancestor components where the exception happened. - // - // eslint-disable-next-line react-internal/safe-string-coercion - return "" + value; -} -function checkKeyStringCoercion(value) { - { - if (willCoercionThrow(value)) { - error( - "The provided key is an unsupported type %s." + - " This value must be coerced to a string before using it here.", - typeName(value) - ); + var defineDeprecationWarning = function (methodName, info) { + Object.defineProperty(Component.prototype, methodName, { + get: function () { + warn( + "%s(...) is deprecated in plain JavaScript React classes. %s", + info[0], + info[1] + ); - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) - } - } -} + return undefined; + } + }); + }; -// Re-export dynamic flags from the www version. -var dynamicFeatureFlags = require("ReactFeatureFlags"); - -var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, - enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing; -// On WWW, false is used for a new modern build. - -function getWrappedName(outerType, innerType, wrapperName) { - var displayName = outerType.displayName; - - if (displayName) { - return displayName; - } - - var functionName = innerType.displayName || innerType.name || ""; - return functionName !== "" - ? wrapperName + "(" + functionName + ")" - : wrapperName; -} // Keep in sync with react-reconciler/getComponentNameFromFiber - -function getContextName(type) { - return type.displayName || "Context"; -} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. - -function getComponentNameFromType(type) { - if (type == null) { - // Host root, text node or just invalid type. - return null; - } - - { - if (typeof type.tag === "number") { - error( - "Received an unexpected object in getComponentNameFromType(). " + - "This is likely a bug in React. Please file an issue." - ); + for (var fnName in deprecatedAPIs) { + if (deprecatedAPIs.hasOwnProperty(fnName)) { + defineDeprecationWarning(fnName, deprecatedAPIs[fnName]); + } + } } - } - if (typeof type === "function") { - return type.displayName || type.name || null; - } + function ComponentDummy() {} - if (typeof type === "string") { - return type; - } + ComponentDummy.prototype = Component.prototype; + /** + * Convenience component with default shallow equality check for sCU. + */ - switch (type) { - case REACT_FRAGMENT_TYPE: - return "Fragment"; + function PureComponent(props, context, updater) { + this.props = props; + this.context = context; // If a component has string refs, we will assign a different object later. - case REACT_PORTAL_TYPE: - return "Portal"; + this.refs = emptyObject; + this.updater = updater || ReactNoopUpdateQueue; + } - case REACT_PROFILER_TYPE: - return "Profiler"; + var pureComponentPrototype = (PureComponent.prototype = + new ComponentDummy()); + pureComponentPrototype.constructor = PureComponent; // Avoid an extra prototype jump for these methods. - case REACT_STRICT_MODE_TYPE: - return "StrictMode"; + assign(pureComponentPrototype, Component.prototype); + pureComponentPrototype.isPureReactComponent = true; - case REACT_SUSPENSE_TYPE: - return "Suspense"; + // an immutable object with a single mutable value + function createRef() { + var refObject = { + current: null + }; - case REACT_SUSPENSE_LIST_TYPE: - return "SuspenseList"; + { + Object.seal(refObject); + } - case REACT_CACHE_TYPE: { - return "Cache"; + return refObject; } - // Fall through - - case REACT_TRACING_MARKER_TYPE: - if (enableTransitionTracing) { - return "TracingMarker"; - } - } + var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_CONTEXT_TYPE: - var context = type; - return getContextName(context) + ".Consumer"; - - case REACT_PROVIDER_TYPE: - var provider = type; - return getContextName(provider._context) + ".Provider"; + function isArray(a) { + return isArrayImpl(a); + } - case REACT_FORWARD_REF_TYPE: - return getWrappedName(type, type.render, "ForwardRef"); + /* + * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol + * and Temporal.* types. See https://github.com/facebook/react/pull/22064. + * + * The functions in this module will throw an easier-to-understand, + * easier-to-debug exception with a clear errors message message explaining the + * problem. (Instead of a confusing exception thrown inside the implementation + * of the `value` object). + */ + // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. + function typeName(value) { + { + // toStringTag is needed for namespaced types like Temporal.Instant + var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; + var type = + (hasToStringTag && value[Symbol.toStringTag]) || + value.constructor.name || + "Object"; // $FlowFixMe[incompatible-return] - case REACT_MEMO_TYPE: - var outerName = type.displayName || null; + return type; + } + } // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - if (outerName !== null) { - return outerName; + function willCoercionThrow(value) { + { + try { + testStringCoercion(value); + return false; + } catch (e) { + return true; } + } + } - return getComponentNameFromType(type.type) || "Memo"; - - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + function testStringCoercion(value) { + // If you ended up here by following an exception call stack, here's what's + // happened: you supplied an object or symbol value to React (as a prop, key, + // DOM attribute, CSS property, string ref, etc.) and when React tried to + // coerce it to a string using `'' + value`, an exception was thrown. + // + // The most common types that will cause this exception are `Symbol` instances + // and Temporal objects like `Temporal.Instant`. But any object that has a + // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this + // exception. (Library authors do this to prevent users from using built-in + // numeric operators like `+` or comparison operators like `>=` because custom + // methods are needed to perform accurate arithmetic or comparison.) + // + // To fix the problem, coerce this object or symbol value to a string before + // passing it to React. The most reliable way is usually `String(value)`. + // + // To find which value is throwing, check the browser or debugger console. + // Before this exception was thrown, there should be `console.error` output + // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the + // problem and how that type was used: key, atrribute, input value prop, etc. + // In most cases, this console output also shows the component and its + // ancestor components where the exception happened. + // + // eslint-disable-next-line react-internal/safe-string-coercion + return "" + value; + } + function checkKeyStringCoercion(value) { + { + if (willCoercionThrow(value)) { + error( + "The provided key is an unsupported type %s." + + " This value must be coerced to a string before using it here.", + typeName(value) + ); - try { - return getComponentNameFromType(init(payload)); - } catch (x) { - return null; + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } } } - } - - return null; -} -// $FlowFixMe[method-unbinding] -var hasOwnProperty = Object.prototype.hasOwnProperty; + // Re-export dynamic flags from the www version. + var dynamicFeatureFlags = require("ReactFeatureFlags"); -/** - * Keeps track of the current owner. - * - * The current owner is the component who should own any components that are - * currently being constructed. - */ -var ReactCurrentOwner$2 = { - /** - * @internal - * @type {ReactComponent} - */ - current: null -}; - -var RESERVED_PROPS$1 = { - key: true, - ref: true, - __self: true, - __source: true -}; -var specialPropKeyWarningShown$1, - specialPropRefWarningShown$1, - didWarnAboutStringRefs$1; - -{ - didWarnAboutStringRefs$1 = {}; -} + var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, + enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing; + // On WWW, false is used for a new modern build. -function hasValidRef$1(config) { - { - if (hasOwnProperty.call(config, "ref")) { - var getter = Object.getOwnPropertyDescriptor(config, "ref").get; + function getWrappedName(outerType, innerType, wrapperName) { + var displayName = outerType.displayName; - if (getter && getter.isReactWarning) { - return false; + if (displayName) { + return displayName; } - } - } - return config.ref !== undefined; -} + var functionName = innerType.displayName || innerType.name || ""; + return functionName !== "" + ? wrapperName + "(" + functionName + ")" + : wrapperName; + } // Keep in sync with react-reconciler/getComponentNameFromFiber -function hasValidKey$1(config) { - { - if (hasOwnProperty.call(config, "key")) { - var getter = Object.getOwnPropertyDescriptor(config, "key").get; + function getContextName(type) { + return type.displayName || "Context"; + } // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. - if (getter && getter.isReactWarning) { - return false; + function getComponentNameFromType(type) { + if (type == null) { + // Host root, text node or just invalid type. + return null; } - } - } - return config.key !== undefined; -} + { + if (typeof type.tag === "number") { + error( + "Received an unexpected object in getComponentNameFromType(). " + + "This is likely a bug in React. Please file an issue." + ); + } + } -function defineKeyPropWarningGetter$1(props, displayName) { - var warnAboutAccessingKey = function () { - { - if (!specialPropKeyWarningShown$1) { - specialPropKeyWarningShown$1 = true; + if (typeof type === "function") { + return type.displayName || type.name || null; + } - error( - "%s: `key` is not a prop. Trying to access it will result " + - "in `undefined` being returned. If you need to access the same " + - "value within the child component, you should pass it as a different " + - "prop. (https://reactjs.org/link/special-props)", - displayName - ); + if (typeof type === "string") { + return type; } - } - }; - warnAboutAccessingKey.isReactWarning = true; - Object.defineProperty(props, "key", { - get: warnAboutAccessingKey, - configurable: true - }); -} + switch (type) { + case REACT_FRAGMENT_TYPE: + return "Fragment"; -function defineRefPropWarningGetter$1(props, displayName) { - var warnAboutAccessingRef = function () { - { - if (!specialPropRefWarningShown$1) { - specialPropRefWarningShown$1 = true; + case REACT_PORTAL_TYPE: + return "Portal"; - error( - "%s: `ref` is not a prop. Trying to access it will result " + - "in `undefined` being returned. If you need to access the same " + - "value within the child component, you should pass it as a different " + - "prop. (https://reactjs.org/link/special-props)", - displayName - ); - } - } - }; + case REACT_PROFILER_TYPE: + return "Profiler"; - warnAboutAccessingRef.isReactWarning = true; - Object.defineProperty(props, "ref", { - get: warnAboutAccessingRef, - configurable: true - }); -} + case REACT_STRICT_MODE_TYPE: + return "StrictMode"; -function warnIfStringRefCannotBeAutoConverted$1(config) { - { - if ( - typeof config.ref === "string" && - ReactCurrentOwner$2.current && - config.__self && - ReactCurrentOwner$2.current.stateNode !== config.__self - ) { - var componentName = getComponentNameFromType( - ReactCurrentOwner$2.current.type - ); + case REACT_SUSPENSE_TYPE: + return "Suspense"; - if (!didWarnAboutStringRefs$1[componentName]) { - error( - 'Component "%s" contains the string ref "%s". ' + - "Support for string refs will be removed in a future major release. " + - "This case cannot be automatically converted to an arrow function. " + - "We ask you to manually fix this case by using useRef() or createRef() instead. " + - "Learn more about using refs safely here: " + - "https://reactjs.org/link/strict-mode-string-ref", - componentName, - config.ref - ); + case REACT_SUSPENSE_LIST_TYPE: + return "SuspenseList"; - didWarnAboutStringRefs$1[componentName] = true; - } - } - } -} -/** - * Factory method to create a new React element. This no longer adheres to - * the class pattern, so do not use new to call it. Also, instanceof check - * will not work. Instead test $$typeof field against Symbol.for('react.element') to check - * if something is a React Element. - * - * @param {*} type - * @param {*} props - * @param {*} key - * @param {string|object} ref - * @param {*} owner - * @param {*} self A *temporary* helper to detect places where `this` is - * different from the `owner` when React.createElement is called, so that we - * can warn. We want to get rid of owner and replace string `ref`s with arrow - * functions, and as long as `this` and owner are the same, there will be no - * change in behavior. - * @param {*} source An annotation object (added by a transpiler or otherwise) - * indicating filename, line number, and/or other information. - * @internal - */ + case REACT_CACHE_TYPE: { + return "Cache"; + } -function ReactElement$1(type, key, ref, self, source, owner, props) { - var element = { - // This tag allows us to uniquely identify this as a React Element - $$typeof: REACT_ELEMENT_TYPE, - // Built-in properties that belong on the element - type: type, - key: key, - ref: ref, - props: props, - // Record the component responsible for creating this element. - _owner: owner - }; - - { - // The validation flag is currently mutative. We put it on - // an external backing store so that we can freeze the whole object. - // This can be replaced with a WeakMap once they are implemented in - // commonly used development environments. - element._store = {}; // To make comparing ReactElements easier for testing purposes, we make - // the validation flag non-enumerable (where possible, which should - // include every environment we run tests in), so the test framework - // ignores it. - - Object.defineProperty(element._store, "validated", { - configurable: false, - enumerable: false, - writable: true, - value: false - }); // self and source are DEV only properties. - - Object.defineProperty(element, "_self", { - configurable: false, - enumerable: false, - writable: false, - value: self - }); // Two elements created in two different places should be considered - // equal for testing purposes and therefore we hide it from enumeration. - - Object.defineProperty(element, "_source", { - configurable: false, - enumerable: false, - writable: false, - value: source - }); - - if (Object.freeze) { - Object.freeze(element.props); - Object.freeze(element); - } - } + // Fall through - return element; -} -/** - * Create and return a new ReactElement of the given type. - * See https://reactjs.org/docs/react-api.html#createelement - */ + case REACT_TRACING_MARKER_TYPE: + if (enableTransitionTracing) { + return "TracingMarker"; + } + } -function createElement$1(type, config, children) { - var propName; // Reserved names are extracted + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_CONTEXT_TYPE: + var context = type; + return getContextName(context) + ".Consumer"; - var props = {}; - var key = null; - var ref = null; - var self = null; - var source = null; + case REACT_PROVIDER_TYPE: + var provider = type; + return getContextName(provider._context) + ".Provider"; - if (config != null) { - if (hasValidRef$1(config)) { - ref = config.ref; + case REACT_FORWARD_REF_TYPE: + return getWrappedName(type, type.render, "ForwardRef"); - { - warnIfStringRefCannotBeAutoConverted$1(config); - } - } + case REACT_MEMO_TYPE: + var outerName = type.displayName || null; - if (hasValidKey$1(config)) { - { - checkKeyStringCoercion(config.key); - } + if (outerName !== null) { + return outerName; + } - key = "" + config.key; - } + return getComponentNameFromType(type.type) || "Memo"; - self = config.__self === undefined ? null : config.__self; - source = config.__source === undefined ? null : config.__source; // Remaining properties are added to a new props object + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - for (propName in config) { - if ( - hasOwnProperty.call(config, propName) && - !RESERVED_PROPS$1.hasOwnProperty(propName) - ) { - props[propName] = config[propName]; + try { + return getComponentNameFromType(init(payload)); + } catch (x) { + return null; + } + } + } } - } - } // Children can be more than one argument, and those are transferred onto - // the newly allocated props object. - var childrenLength = arguments.length - 2; + return null; + } - if (childrenLength === 1) { - props.children = children; - } else if (childrenLength > 1) { - var childArray = Array(childrenLength); + // $FlowFixMe[method-unbinding] + var hasOwnProperty = Object.prototype.hasOwnProperty; + + /** + * Keeps track of the current owner. + * + * The current owner is the component who should own any components that are + * currently being constructed. + */ + var ReactCurrentOwner$2 = { + /** + * @internal + * @type {ReactComponent} + */ + current: null + }; - for (var i = 0; i < childrenLength; i++) { - childArray[i] = arguments[i + 2]; - } + var RESERVED_PROPS$1 = { + key: true, + ref: true, + __self: true, + __source: true + }; + var specialPropKeyWarningShown$1, + specialPropRefWarningShown$1, + didWarnAboutStringRefs$1; { - if (Object.freeze) { - Object.freeze(childArray); - } + didWarnAboutStringRefs$1 = {}; } - props.children = childArray; - } // Resolve default props - - if (type && type.defaultProps) { - var defaultProps = type.defaultProps; + function hasValidRef$1(config) { + { + if (hasOwnProperty.call(config, "ref")) { + var getter = Object.getOwnPropertyDescriptor(config, "ref").get; - for (propName in defaultProps) { - if (props[propName] === undefined) { - props[propName] = defaultProps[propName]; + if (getter && getter.isReactWarning) { + return false; + } + } } + + return config.ref !== undefined; } - } - { - if (key || ref) { - var displayName = - typeof type === "function" - ? type.displayName || type.name || "Unknown" - : type; + function hasValidKey$1(config) { + { + if (hasOwnProperty.call(config, "key")) { + var getter = Object.getOwnPropertyDescriptor(config, "key").get; - if (key) { - defineKeyPropWarningGetter$1(props, displayName); + if (getter && getter.isReactWarning) { + return false; + } + } } - if (ref) { - defineRefPropWarningGetter$1(props, displayName); - } + return config.key !== undefined; } - } - - return ReactElement$1( - type, - key, - ref, - self, - source, - ReactCurrentOwner$2.current, - props - ); -} -function cloneAndReplaceKey(oldElement, newKey) { - var newElement = ReactElement$1( - oldElement.type, - newKey, - oldElement.ref, - oldElement._self, - oldElement._source, - oldElement._owner, - oldElement.props - ); - return newElement; -} -/** - * Clone and return a new ReactElement using element as the starting point. - * See https://reactjs.org/docs/react-api.html#cloneelement - */ - -function cloneElement$1(element, config, children) { - if (element === null || element === undefined) { - throw new Error( - "React.cloneElement(...): The argument must be a React element, but you passed " + - element + - "." - ); - } - var propName; // Original props are copied - - var props = assign({}, element.props); // Reserved names are extracted + function defineKeyPropWarningGetter$1(props, displayName) { + var warnAboutAccessingKey = function () { + { + if (!specialPropKeyWarningShown$1) { + specialPropKeyWarningShown$1 = true; - var key = element.key; - var ref = element.ref; // Self is preserved since the owner is preserved. + error( + "%s: `key` is not a prop. Trying to access it will result " + + "in `undefined` being returned. If you need to access the same " + + "value within the child component, you should pass it as a different " + + "prop. (https://reactjs.org/link/special-props)", + displayName + ); + } + } + }; - var self = element._self; // Source is preserved since cloneElement is unlikely to be targeted by a - // transpiler, and the original source is probably a better indicator of the - // true owner. + warnAboutAccessingKey.isReactWarning = true; + Object.defineProperty(props, "key", { + get: warnAboutAccessingKey, + configurable: true + }); + } - var source = element._source; // Owner will be preserved, unless ref is overridden + function defineRefPropWarningGetter$1(props, displayName) { + var warnAboutAccessingRef = function () { + { + if (!specialPropRefWarningShown$1) { + specialPropRefWarningShown$1 = true; - var owner = element._owner; + error( + "%s: `ref` is not a prop. Trying to access it will result " + + "in `undefined` being returned. If you need to access the same " + + "value within the child component, you should pass it as a different " + + "prop. (https://reactjs.org/link/special-props)", + displayName + ); + } + } + }; - if (config != null) { - if (hasValidRef$1(config)) { - // Silently steal the ref from the parent. - ref = config.ref; - owner = ReactCurrentOwner$2.current; + warnAboutAccessingRef.isReactWarning = true; + Object.defineProperty(props, "ref", { + get: warnAboutAccessingRef, + configurable: true + }); } - if (hasValidKey$1(config)) { + function warnIfStringRefCannotBeAutoConverted$1(config) { { - checkKeyStringCoercion(config.key); - } - - key = "" + config.key; - } // Remaining properties override existing props - - var defaultProps; + if ( + typeof config.ref === "string" && + ReactCurrentOwner$2.current && + config.__self && + ReactCurrentOwner$2.current.stateNode !== config.__self + ) { + var componentName = getComponentNameFromType( + ReactCurrentOwner$2.current.type + ); - if (element.type && element.type.defaultProps) { - defaultProps = element.type.defaultProps; - } + if (!didWarnAboutStringRefs$1[componentName]) { + error( + 'Component "%s" contains the string ref "%s". ' + + "Support for string refs will be removed in a future major release. " + + "This case cannot be automatically converted to an arrow function. " + + "We ask you to manually fix this case by using useRef() or createRef() instead. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-string-ref", + componentName, + config.ref + ); - for (propName in config) { - if ( - hasOwnProperty.call(config, propName) && - !RESERVED_PROPS$1.hasOwnProperty(propName) - ) { - if (config[propName] === undefined && defaultProps !== undefined) { - // Resolve default props - props[propName] = defaultProps[propName]; - } else { - props[propName] = config[propName]; + didWarnAboutStringRefs$1[componentName] = true; + } } } } - } // Children can be more than one argument, and those are transferred onto - // the newly allocated props object. + /** + * Factory method to create a new React element. This no longer adheres to + * the class pattern, so do not use new to call it. Also, instanceof check + * will not work. Instead test $$typeof field against Symbol.for('react.element') to check + * if something is a React Element. + * + * @param {*} type + * @param {*} props + * @param {*} key + * @param {string|object} ref + * @param {*} owner + * @param {*} self A *temporary* helper to detect places where `this` is + * different from the `owner` when React.createElement is called, so that we + * can warn. We want to get rid of owner and replace string `ref`s with arrow + * functions, and as long as `this` and owner are the same, there will be no + * change in behavior. + * @param {*} source An annotation object (added by a transpiler or otherwise) + * indicating filename, line number, and/or other information. + * @internal + */ + + function ReactElement$1(type, key, ref, self, source, owner, props) { + var element = { + // This tag allows us to uniquely identify this as a React Element + $$typeof: REACT_ELEMENT_TYPE, + // Built-in properties that belong on the element + type: type, + key: key, + ref: ref, + props: props, + // Record the component responsible for creating this element. + _owner: owner + }; - var childrenLength = arguments.length - 2; + { + // The validation flag is currently mutative. We put it on + // an external backing store so that we can freeze the whole object. + // This can be replaced with a WeakMap once they are implemented in + // commonly used development environments. + element._store = {}; // To make comparing ReactElements easier for testing purposes, we make + // the validation flag non-enumerable (where possible, which should + // include every environment we run tests in), so the test framework + // ignores it. + + Object.defineProperty(element._store, "validated", { + configurable: false, + enumerable: false, + writable: true, + value: false + }); // self and source are DEV only properties. + + Object.defineProperty(element, "_self", { + configurable: false, + enumerable: false, + writable: false, + value: self + }); // Two elements created in two different places should be considered + // equal for testing purposes and therefore we hide it from enumeration. + + Object.defineProperty(element, "_source", { + configurable: false, + enumerable: false, + writable: false, + value: source + }); - if (childrenLength === 1) { - props.children = children; - } else if (childrenLength > 1) { - var childArray = Array(childrenLength); + if (Object.freeze) { + Object.freeze(element.props); + Object.freeze(element); + } + } - for (var i = 0; i < childrenLength; i++) { - childArray[i] = arguments[i + 2]; + return element; } + /** + * Create and return a new ReactElement of the given type. + * See https://reactjs.org/docs/react-api.html#createelement + */ + + function createElement$1(type, config, children) { + var propName; // Reserved names are extracted + + var props = {}; + var key = null; + var ref = null; + var self = null; + var source = null; + + if (config != null) { + if (hasValidRef$1(config)) { + ref = config.ref; + + { + warnIfStringRefCannotBeAutoConverted$1(config); + } + } - props.children = childArray; - } + if (hasValidKey$1(config)) { + { + checkKeyStringCoercion(config.key); + } - return ReactElement$1(element.type, key, ref, self, source, owner, props); -} -/** - * Verifies the object is a ReactElement. - * See https://reactjs.org/docs/react-api.html#isvalidelement - * @param {?object} object - * @return {boolean} True if `object` is a ReactElement. - * @final - */ + key = "" + config.key; + } -function isValidElement$1(object) { - return ( - typeof object === "object" && - object !== null && - object.$$typeof === REACT_ELEMENT_TYPE - ); -} + self = config.__self === undefined ? null : config.__self; + source = config.__source === undefined ? null : config.__source; // Remaining properties are added to a new props object -var SEPARATOR = "."; -var SUBSEPARATOR = ":"; -/** - * Escape and wrap key so it is safe to use as a reactid - * - * @param {string} key to be escaped. - * @return {string} the escaped key. - */ + for (propName in config) { + if ( + hasOwnProperty.call(config, propName) && + !RESERVED_PROPS$1.hasOwnProperty(propName) + ) { + props[propName] = config[propName]; + } + } + } // Children can be more than one argument, and those are transferred onto + // the newly allocated props object. -function escape(key) { - var escapeRegex = /[=:]/g; - var escaperLookup = { - "=": "=0", - ":": "=2" - }; - var escapedString = key.replace(escapeRegex, function (match) { - return escaperLookup[match]; - }); - return "$" + escapedString; -} -/** - * TODO: Test that a single child and an array with one item have the same key - * pattern. - */ + var childrenLength = arguments.length - 2; -var didWarnAboutMaps = false; -var userProvidedKeyEscapeRegex = /\/+/g; + if (childrenLength === 1) { + props.children = children; + } else if (childrenLength > 1) { + var childArray = Array(childrenLength); -function escapeUserProvidedKey(text) { - return text.replace(userProvidedKeyEscapeRegex, "$&/"); -} -/** - * Generate a key string that identifies a element within a set. - * - * @param {*} element A element that could contain a manual key. - * @param {number} index Index that is used if a manual key is not provided. - * @return {string} - */ + for (var i = 0; i < childrenLength; i++) { + childArray[i] = arguments[i + 2]; + } -function getElementKey(element, index) { - // Do some typechecking here since we call this blindly. We want to ensure - // that we don't block potential future ES APIs. - if (typeof element === "object" && element !== null && element.key != null) { - // Explicit key - { - checkKeyStringCoercion(element.key); + { + if (Object.freeze) { + Object.freeze(childArray); + } + } + + props.children = childArray; + } // Resolve default props + + if (type && type.defaultProps) { + var defaultProps = type.defaultProps; + + for (propName in defaultProps) { + if (props[propName] === undefined) { + props[propName] = defaultProps[propName]; + } + } + } + + { + if (key || ref) { + var displayName = + typeof type === "function" + ? type.displayName || type.name || "Unknown" + : type; + + if (key) { + defineKeyPropWarningGetter$1(props, displayName); + } + + if (ref) { + defineRefPropWarningGetter$1(props, displayName); + } + } + } + + return ReactElement$1( + type, + key, + ref, + self, + source, + ReactCurrentOwner$2.current, + props + ); + } + function cloneAndReplaceKey(oldElement, newKey) { + var newElement = ReactElement$1( + oldElement.type, + newKey, + oldElement.ref, + oldElement._self, + oldElement._source, + oldElement._owner, + oldElement.props + ); + return newElement; } + /** + * Clone and return a new ReactElement using element as the starting point. + * See https://reactjs.org/docs/react-api.html#cloneelement + */ + + function cloneElement$1(element, config, children) { + if (element === null || element === undefined) { + throw new Error( + "React.cloneElement(...): The argument must be a React element, but you passed " + + element + + "." + ); + } - return escape("" + element.key); - } // Implicit key determined by the index in the set + var propName; // Original props are copied - return index.toString(36); -} + var props = assign({}, element.props); // Reserved names are extracted -function mapIntoArray(children, array, escapedPrefix, nameSoFar, callback) { - var type = typeof children; + var key = element.key; + var ref = element.ref; // Self is preserved since the owner is preserved. - if (type === "undefined" || type === "boolean") { - // All of the above are perceived as null. - children = null; - } + var self = element._self; // Source is preserved since cloneElement is unlikely to be targeted by a + // transpiler, and the original source is probably a better indicator of the + // true owner. - var invokeCallback = false; + var source = element._source; // Owner will be preserved, unless ref is overridden - if (children === null) { - invokeCallback = true; - } else { - switch (type) { - case "string": - case "number": - invokeCallback = true; - break; + var owner = element._owner; - case "object": - switch (children.$$typeof) { - case REACT_ELEMENT_TYPE: - case REACT_PORTAL_TYPE: - invokeCallback = true; + if (config != null) { + if (hasValidRef$1(config)) { + // Silently steal the ref from the parent. + ref = config.ref; + owner = ReactCurrentOwner$2.current; } - } - } - if (invokeCallback) { - var _child = children; - var mappedChild = callback(_child); // If it's the only child, treat the name as if it was wrapped in an array - // so that it's consistent if the number of children grows: + if (hasValidKey$1(config)) { + { + checkKeyStringCoercion(config.key); + } - var childKey = - nameSoFar === "" ? SEPARATOR + getElementKey(_child, 0) : nameSoFar; + key = "" + config.key; + } // Remaining properties override existing props - if (isArray(mappedChild)) { - var escapedChildKey = ""; + var defaultProps; - if (childKey != null) { - escapedChildKey = escapeUserProvidedKey(childKey) + "/"; - } + if (element.type && element.type.defaultProps) { + defaultProps = element.type.defaultProps; + } - mapIntoArray(mappedChild, array, escapedChildKey, "", function (c) { - return c; - }); - } else if (mappedChild != null) { - if (isValidElement$1(mappedChild)) { - { - // The `if` statement here prevents auto-disabling of the safe - // coercion ESLint rule, so we must manually disable it below. - // $FlowFixMe[incompatible-type] Flow incorrectly thinks React.Portal doesn't have a key - if (mappedChild.key && (!_child || _child.key !== mappedChild.key)) { - checkKeyStringCoercion(mappedChild.key); + for (propName in config) { + if ( + hasOwnProperty.call(config, propName) && + !RESERVED_PROPS$1.hasOwnProperty(propName) + ) { + if (config[propName] === undefined && defaultProps !== undefined) { + // Resolve default props + props[propName] = defaultProps[propName]; + } else { + props[propName] = config[propName]; + } } } + } // Children can be more than one argument, and those are transferred onto + // the newly allocated props object. - mappedChild = cloneAndReplaceKey( - mappedChild, // Keep both the (mapped) and old keys if they differ, just as - // traverseAllChildren used to do for objects as children - escapedPrefix + // $FlowFixMe[incompatible-type] Flow incorrectly thinks React.Portal doesn't have a key - (mappedChild.key && (!_child || _child.key !== mappedChild.key) - ? escapeUserProvidedKey( - // $FlowFixMe[unsafe-addition] - "" + mappedChild.key // eslint-disable-line react-internal/safe-string-coercion - ) + "/" - : "") + - childKey - ); + var childrenLength = arguments.length - 2; + + if (childrenLength === 1) { + props.children = children; + } else if (childrenLength > 1) { + var childArray = Array(childrenLength); + + for (var i = 0; i < childrenLength; i++) { + childArray[i] = arguments[i + 2]; + } + + props.children = childArray; } - array.push(mappedChild); + return ReactElement$1(element.type, key, ref, self, source, owner, props); } - - return 1; - } - - var child; - var nextName; - var subtreeCount = 0; // Count of children found in the current subtree. - - var nextNamePrefix = nameSoFar === "" ? SEPARATOR : nameSoFar + SUBSEPARATOR; - - if (isArray(children)) { - for (var i = 0; i < children.length; i++) { - child = children[i]; - nextName = nextNamePrefix + getElementKey(child, i); - subtreeCount += mapIntoArray( - child, - array, - escapedPrefix, - nextName, - callback + /** + * Verifies the object is a ReactElement. + * See https://reactjs.org/docs/react-api.html#isvalidelement + * @param {?object} object + * @return {boolean} True if `object` is a ReactElement. + * @final + */ + + function isValidElement$1(object) { + return ( + typeof object === "object" && + object !== null && + object.$$typeof === REACT_ELEMENT_TYPE ); } - } else { - var iteratorFn = getIteratorFn(children); - if (typeof iteratorFn === "function") { - var iterableChildren = children; + var SEPARATOR = "."; + var SUBSEPARATOR = ":"; + /** + * Escape and wrap key so it is safe to use as a reactid + * + * @param {string} key to be escaped. + * @return {string} the escaped key. + */ + + function escape(key) { + var escapeRegex = /[=:]/g; + var escaperLookup = { + "=": "=0", + ":": "=2" + }; + var escapedString = key.replace(escapeRegex, function (match) { + return escaperLookup[match]; + }); + return "$" + escapedString; + } + /** + * TODO: Test that a single child and an array with one item have the same key + * pattern. + */ - { - // Warn about using Maps as children - if (iteratorFn === iterableChildren.entries) { - if (!didWarnAboutMaps) { - warn( - "Using Maps as children is not supported. " + - "Use an array of keyed ReactElements instead." - ); - } + var didWarnAboutMaps = false; + var userProvidedKeyEscapeRegex = /\/+/g; - didWarnAboutMaps = true; + function escapeUserProvidedKey(text) { + return text.replace(userProvidedKeyEscapeRegex, "$&/"); + } + /** + * Generate a key string that identifies a element within a set. + * + * @param {*} element A element that could contain a manual key. + * @param {number} index Index that is used if a manual key is not provided. + * @return {string} + */ + + function getElementKey(element, index) { + // Do some typechecking here since we call this blindly. We want to ensure + // that we don't block potential future ES APIs. + if ( + typeof element === "object" && + element !== null && + element.key != null + ) { + // Explicit key + { + checkKeyStringCoercion(element.key); } - } - var iterator = iteratorFn.call(iterableChildren); - var step; - var ii = 0; // $FlowFixMe[incompatible-use] `iteratorFn` might return null according to typing. - - while (!(step = iterator.next()).done) { - child = step.value; - nextName = nextNamePrefix + getElementKey(child, ii++); - subtreeCount += mapIntoArray( - child, - array, - escapedPrefix, - nextName, - callback - ); - } - } else if (type === "object") { - // eslint-disable-next-line react-internal/safe-string-coercion - var childrenString = String(children); - throw new Error( - "Objects are not valid as a React child (found: " + - (childrenString === "[object Object]" - ? "object with keys {" + Object.keys(children).join(", ") + "}" - : childrenString) + - "). " + - "If you meant to render a collection of children, use an array " + - "instead." - ); + return escape("" + element.key); + } // Implicit key determined by the index in the set + + return index.toString(36); } - } - return subtreeCount; -} -/** - * Maps children that are typically specified as `props.children`. - * - * See https://reactjs.org/docs/react-api.html#reactchildrenmap - * - * The provided mapFunction(child, index) will be called for each - * leaf child. - * - * @param {?*} children Children tree container. - * @param {function(*, int)} func The map function. - * @param {*} context Context for mapFunction. - * @return {object} Object containing the ordered map of results. - */ + function mapIntoArray(children, array, escapedPrefix, nameSoFar, callback) { + var type = typeof children; -function mapChildren(children, func, context) { - if (children == null) { - return children; - } - - var result = []; - var count = 0; - mapIntoArray(children, result, "", "", function (child) { - return func.call(context, child, count++); - }); - return result; -} -/** - * Count the number of children that are typically specified as - * `props.children`. - * - * See https://reactjs.org/docs/react-api.html#reactchildrencount - * - * @param {?*} children Children tree container. - * @return {number} The number of children. - */ + if (type === "undefined" || type === "boolean") { + // All of the above are perceived as null. + children = null; + } -function countChildren(children) { - var n = 0; - mapChildren(children, function () { - n++; // Don't return anything - }); - return n; -} -/** - * Iterates through children that are typically specified as `props.children`. - * - * See https://reactjs.org/docs/react-api.html#reactchildrenforeach - * - * The provided forEachFunc(child, index) will be called for each - * leaf child. - * - * @param {?*} children Children tree container. - * @param {function(*, int)} forEachFunc - * @param {*} forEachContext Context for forEachContext. - */ + var invokeCallback = false; -function forEachChildren(children, forEachFunc, forEachContext) { - mapChildren( - children, // $FlowFixMe[missing-this-annot] - function () { - forEachFunc.apply(this, arguments); // Don't return anything. - }, - forEachContext - ); -} -/** - * Flatten a children object (typically specified as `props.children`) and - * return an array with appropriately re-keyed children. - * - * See https://reactjs.org/docs/react-api.html#reactchildrentoarray - */ + if (children === null) { + invokeCallback = true; + } else { + switch (type) { + case "string": + case "number": + invokeCallback = true; + break; -function toArray(children) { - return ( - mapChildren(children, function (child) { - return child; - }) || [] - ); -} -/** - * Returns the first child in a collection of children and verifies that there - * is only one child in the collection. - * - * See https://reactjs.org/docs/react-api.html#reactchildrenonly - * - * The current implementation of this function assumes that a single child gets - * passed without a wrapper, but the purpose of this helper function is to - * abstract away the particular structure of children. - * - * @param {?object} children Child collection structure. - * @return {ReactElement} The first and only `ReactElement` contained in the - * structure. - */ + case "object": + switch (children.$$typeof) { + case REACT_ELEMENT_TYPE: + case REACT_PORTAL_TYPE: + invokeCallback = true; + } + } + } -function onlyChild(children) { - if (!isValidElement$1(children)) { - throw new Error( - "React.Children.only expected to receive a single React element child." - ); - } + if (invokeCallback) { + var _child = children; + var mappedChild = callback(_child); // If it's the only child, treat the name as if it was wrapped in an array + // so that it's consistent if the number of children grows: - return children; -} + var childKey = + nameSoFar === "" ? SEPARATOR + getElementKey(_child, 0) : nameSoFar; -function createContext(defaultValue) { - // TODO: Second argument used to be an optional `calculateChangedBits` - // function. Warn to reserve for future use? - var context = { - $$typeof: REACT_CONTEXT_TYPE, - // As a workaround to support multiple concurrent renderers, we categorize - // some renderers as primary and others as secondary. We only expect - // there to be two concurrent renderers at most: React Native (primary) and - // Fabric (secondary); React DOM (primary) and React ART (secondary). - // Secondary renderers store their context values on separate fields. - _currentValue: defaultValue, - _currentValue2: defaultValue, - // Used to track how many concurrent renderers this context currently - // supports within in a single renderer. Such as parallel server rendering. - _threadCount: 0, - // These are circular - Provider: null, - Consumer: null, - // Add these to use same hidden class in VM as ServerContext - _defaultValue: null, - _globalName: null - }; - context.Provider = { - $$typeof: REACT_PROVIDER_TYPE, - _context: context - }; - var hasWarnedAboutUsingNestedContextConsumers = false; - var hasWarnedAboutUsingConsumerProvider = false; - var hasWarnedAboutDisplayNameOnConsumer = false; - - { - // A separate object, but proxies back to the original context object for - // backwards compatibility. It has a different $$typeof, so we can properly - // warn for the incorrect usage of Context as a Consumer. - var Consumer = { - $$typeof: REACT_CONTEXT_TYPE, - _context: context - }; // $FlowFixMe[prop-missing]: Flow complains about not setting a value, which is intentional here - - Object.defineProperties(Consumer, { - Provider: { - get: function () { - if (!hasWarnedAboutUsingConsumerProvider) { - hasWarnedAboutUsingConsumerProvider = true; + if (isArray(mappedChild)) { + var escapedChildKey = ""; - error( - "Rendering is not supported and will be removed in " + - "a future major release. Did you mean to render instead?" - ); + if (childKey != null) { + escapedChildKey = escapeUserProvidedKey(childKey) + "/"; } - return context.Provider; - }, - set: function (_Provider) { - context.Provider = _Provider; - } - }, - _currentValue: { - get: function () { - return context._currentValue; - }, - set: function (_currentValue) { - context._currentValue = _currentValue; - } - }, - _currentValue2: { - get: function () { - return context._currentValue2; - }, - set: function (_currentValue2) { - context._currentValue2 = _currentValue2; - } - }, - _threadCount: { - get: function () { - return context._threadCount; - }, - set: function (_threadCount) { - context._threadCount = _threadCount; - } - }, - Consumer: { - get: function () { - if (!hasWarnedAboutUsingNestedContextConsumers) { - hasWarnedAboutUsingNestedContextConsumers = true; + mapIntoArray(mappedChild, array, escapedChildKey, "", function (c) { + return c; + }); + } else if (mappedChild != null) { + if (isValidElement$1(mappedChild)) { + { + // The `if` statement here prevents auto-disabling of the safe + // coercion ESLint rule, so we must manually disable it below. + // $FlowFixMe[incompatible-type] Flow incorrectly thinks React.Portal doesn't have a key + if ( + mappedChild.key && + (!_child || _child.key !== mappedChild.key) + ) { + checkKeyStringCoercion(mappedChild.key); + } + } - error( - "Rendering is not supported and will be removed in " + - "a future major release. Did you mean to render instead?" + mappedChild = cloneAndReplaceKey( + mappedChild, // Keep both the (mapped) and old keys if they differ, just as + // traverseAllChildren used to do for objects as children + escapedPrefix + // $FlowFixMe[incompatible-type] Flow incorrectly thinks React.Portal doesn't have a key + (mappedChild.key && (!_child || _child.key !== mappedChild.key) + ? escapeUserProvidedKey( + // $FlowFixMe[unsafe-addition] + "" + mappedChild.key // eslint-disable-line react-internal/safe-string-coercion + ) + "/" + : "") + + childKey ); } - return context.Consumer; + array.push(mappedChild); } - }, - displayName: { - get: function () { - return context.displayName; - }, - set: function (displayName) { - if (!hasWarnedAboutDisplayNameOnConsumer) { - warn( - "Setting `displayName` on Context.Consumer has no effect. " + - "You should set it directly on the context with Context.displayName = '%s'.", - displayName - ); - hasWarnedAboutDisplayNameOnConsumer = true; - } - } + return 1; } - }); // $FlowFixMe[prop-missing]: Flow complains about missing properties because it doesn't understand defineProperty - context.Consumer = Consumer; - } + var child; + var nextName; + var subtreeCount = 0; // Count of children found in the current subtree. + + var nextNamePrefix = + nameSoFar === "" ? SEPARATOR : nameSoFar + SUBSEPARATOR; + + if (isArray(children)) { + for (var i = 0; i < children.length; i++) { + child = children[i]; + nextName = nextNamePrefix + getElementKey(child, i); + subtreeCount += mapIntoArray( + child, + array, + escapedPrefix, + nextName, + callback + ); + } + } else { + var iteratorFn = getIteratorFn(children); + + if (typeof iteratorFn === "function") { + var iterableChildren = children; + + { + // Warn about using Maps as children + if (iteratorFn === iterableChildren.entries) { + if (!didWarnAboutMaps) { + warn( + "Using Maps as children is not supported. " + + "Use an array of keyed ReactElements instead." + ); + } - { - context._currentRenderer = null; - context._currentRenderer2 = null; - } + didWarnAboutMaps = true; + } + } - return context; -} + var iterator = iteratorFn.call(iterableChildren); + var step; + var ii = 0; // $FlowFixMe[incompatible-use] `iteratorFn` might return null according to typing. -var Uninitialized = -1; -var Pending = 0; -var Resolved = 1; -var Rejected = 2; - -function lazyInitializer(payload) { - if (payload._status === Uninitialized) { - var ctor = payload._result; - var thenable = ctor(); // Transition to the next state. - // This might throw either because it's missing or throws. If so, we treat it - // as still uninitialized and try again next time. Which is the same as what - // happens if the ctor or any wrappers processing the ctor throws. This might - // end up fixing it if the resolution was a concurrency bug. - - thenable.then( - function (moduleObject) { - if (payload._status === Pending || payload._status === Uninitialized) { - // Transition to the next state. - var resolved = payload; - resolved._status = Resolved; - resolved._result = moduleObject; - } - }, - function (error) { - if (payload._status === Pending || payload._status === Uninitialized) { - // Transition to the next state. - var rejected = payload; - rejected._status = Rejected; - rejected._result = error; + while (!(step = iterator.next()).done) { + child = step.value; + nextName = nextNamePrefix + getElementKey(child, ii++); + subtreeCount += mapIntoArray( + child, + array, + escapedPrefix, + nextName, + callback + ); + } + } else if (type === "object") { + // eslint-disable-next-line react-internal/safe-string-coercion + var childrenString = String(children); + throw new Error( + "Objects are not valid as a React child (found: " + + (childrenString === "[object Object]" + ? "object with keys {" + Object.keys(children).join(", ") + "}" + : childrenString) + + "). " + + "If you meant to render a collection of children, use an array " + + "instead." + ); } } - ); - - if (payload._status === Uninitialized) { - // In case, we're still uninitialized, then we're waiting for the thenable - // to resolve. Set it as pending in the meantime. - var pending = payload; - pending._status = Pending; - pending._result = thenable; - } - } - if (payload._status === Resolved) { - var moduleObject = payload._result; - - { - if (moduleObject === undefined) { - error( - "lazy: Expected the result of a dynamic imp" + - "ort() call. " + - "Instead received: %s\n\nYour code should look like: \n " + // Break up imports to avoid accidentally parsing them as dependencies. - "const MyComponent = lazy(() => imp" + - "ort('./MyComponent'))\n\n" + - "Did you accidentally put curly braces around the import?", - moduleObject - ); - } + return subtreeCount; } + /** + * Maps children that are typically specified as `props.children`. + * + * See https://reactjs.org/docs/react-api.html#reactchildrenmap + * + * The provided mapFunction(child, index) will be called for each + * leaf child. + * + * @param {?*} children Children tree container. + * @param {function(*, int)} func The map function. + * @param {*} context Context for mapFunction. + * @return {object} Object containing the ordered map of results. + */ + + function mapChildren(children, func, context) { + if (children == null) { + return children; + } - { - if (!("default" in moduleObject)) { - error( - "lazy: Expected the result of a dynamic imp" + - "ort() call. " + - "Instead received: %s\n\nYour code should look like: \n " + // Break up imports to avoid accidentally parsing them as dependencies. - "const MyComponent = lazy(() => imp" + - "ort('./MyComponent'))", - moduleObject + var result = []; + var count = 0; + mapIntoArray(children, result, "", "", function (child) { + return func.call(context, child, count++); + }); + return result; + } + /** + * Count the number of children that are typically specified as + * `props.children`. + * + * See https://reactjs.org/docs/react-api.html#reactchildrencount + * + * @param {?*} children Children tree container. + * @return {number} The number of children. + */ + + function countChildren(children) { + var n = 0; + mapChildren(children, function () { + n++; // Don't return anything + }); + return n; + } + /** + * Iterates through children that are typically specified as `props.children`. + * + * See https://reactjs.org/docs/react-api.html#reactchildrenforeach + * + * The provided forEachFunc(child, index) will be called for each + * leaf child. + * + * @param {?*} children Children tree container. + * @param {function(*, int)} forEachFunc + * @param {*} forEachContext Context for forEachContext. + */ + + function forEachChildren(children, forEachFunc, forEachContext) { + mapChildren( + children, // $FlowFixMe[missing-this-annot] + function () { + forEachFunc.apply(this, arguments); // Don't return anything. + }, + forEachContext + ); + } + /** + * Flatten a children object (typically specified as `props.children`) and + * return an array with appropriately re-keyed children. + * + * See https://reactjs.org/docs/react-api.html#reactchildrentoarray + */ + + function toArray(children) { + return ( + mapChildren(children, function (child) { + return child; + }) || [] + ); + } + /** + * Returns the first child in a collection of children and verifies that there + * is only one child in the collection. + * + * See https://reactjs.org/docs/react-api.html#reactchildrenonly + * + * The current implementation of this function assumes that a single child gets + * passed without a wrapper, but the purpose of this helper function is to + * abstract away the particular structure of children. + * + * @param {?object} children Child collection structure. + * @return {ReactElement} The first and only `ReactElement` contained in the + * structure. + */ + + function onlyChild(children) { + if (!isValidElement$1(children)) { + throw new Error( + "React.Children.only expected to receive a single React element child." ); } - } - return moduleObject.default; - } else { - throw payload._result; - } -} + return children; + } -function lazy(ctor) { - var payload = { - // We use these fields to store the result. - _status: Uninitialized, - _result: ctor - }; - var lazyType = { - $$typeof: REACT_LAZY_TYPE, - _payload: payload, - _init: lazyInitializer - }; - - { - // In production, this would just set it on the object. - var defaultProps; - var propTypes; // $FlowFixMe[prop-missing] - - Object.defineProperties(lazyType, { - defaultProps: { - configurable: true, - get: function () { - return defaultProps; - }, - // $FlowFixMe[missing-local-annot] - set: function (newDefaultProps) { - error( - "React.lazy(...): It is not supported to assign `defaultProps` to " + - "a lazy component import. Either specify them where the component " + - "is defined, or create a wrapping component around it." - ); + function createContext(defaultValue) { + // TODO: Second argument used to be an optional `calculateChangedBits` + // function. Warn to reserve for future use? + var context = { + $$typeof: REACT_CONTEXT_TYPE, + // As a workaround to support multiple concurrent renderers, we categorize + // some renderers as primary and others as secondary. We only expect + // there to be two concurrent renderers at most: React Native (primary) and + // Fabric (secondary); React DOM (primary) and React ART (secondary). + // Secondary renderers store their context values on separate fields. + _currentValue: defaultValue, + _currentValue2: defaultValue, + // Used to track how many concurrent renderers this context currently + // supports within in a single renderer. Such as parallel server rendering. + _threadCount: 0, + // These are circular + Provider: null, + Consumer: null, + // Add these to use same hidden class in VM as ServerContext + _defaultValue: null, + _globalName: null + }; + context.Provider = { + $$typeof: REACT_PROVIDER_TYPE, + _context: context + }; + var hasWarnedAboutUsingNestedContextConsumers = false; + var hasWarnedAboutUsingConsumerProvider = false; + var hasWarnedAboutDisplayNameOnConsumer = false; - defaultProps = newDefaultProps; // Match production behavior more closely: - // $FlowFixMe[prop-missing] + { + // A separate object, but proxies back to the original context object for + // backwards compatibility. It has a different $$typeof, so we can properly + // warn for the incorrect usage of Context as a Consumer. + var Consumer = { + $$typeof: REACT_CONTEXT_TYPE, + _context: context + }; // $FlowFixMe[prop-missing]: Flow complains about not setting a value, which is intentional here + + Object.defineProperties(Consumer, { + Provider: { + get: function () { + if (!hasWarnedAboutUsingConsumerProvider) { + hasWarnedAboutUsingConsumerProvider = true; + + error( + "Rendering is not supported and will be removed in " + + "a future major release. Did you mean to render instead?" + ); + } - Object.defineProperty(lazyType, "defaultProps", { - enumerable: true - }); - } - }, - propTypes: { - configurable: true, - get: function () { - return propTypes; - }, - // $FlowFixMe[missing-local-annot] - set: function (newPropTypes) { - error( - "React.lazy(...): It is not supported to assign `propTypes` to " + - "a lazy component import. Either specify them where the component " + - "is defined, or create a wrapping component around it." - ); + return context.Provider; + }, + set: function (_Provider) { + context.Provider = _Provider; + } + }, + _currentValue: { + get: function () { + return context._currentValue; + }, + set: function (_currentValue) { + context._currentValue = _currentValue; + } + }, + _currentValue2: { + get: function () { + return context._currentValue2; + }, + set: function (_currentValue2) { + context._currentValue2 = _currentValue2; + } + }, + _threadCount: { + get: function () { + return context._threadCount; + }, + set: function (_threadCount) { + context._threadCount = _threadCount; + } + }, + Consumer: { + get: function () { + if (!hasWarnedAboutUsingNestedContextConsumers) { + hasWarnedAboutUsingNestedContextConsumers = true; + + error( + "Rendering is not supported and will be removed in " + + "a future major release. Did you mean to render instead?" + ); + } - propTypes = newPropTypes; // Match production behavior more closely: - // $FlowFixMe[prop-missing] + return context.Consumer; + } + }, + displayName: { + get: function () { + return context.displayName; + }, + set: function (displayName) { + if (!hasWarnedAboutDisplayNameOnConsumer) { + warn( + "Setting `displayName` on Context.Consumer has no effect. " + + "You should set it directly on the context with Context.displayName = '%s'.", + displayName + ); + + hasWarnedAboutDisplayNameOnConsumer = true; + } + } + } + }); // $FlowFixMe[prop-missing]: Flow complains about missing properties because it doesn't understand defineProperty - Object.defineProperty(lazyType, "propTypes", { - enumerable: true - }); - } + context.Consumer = Consumer; } - }); - } - - return lazyType; -} -function forwardRef(render) { - { - if (render != null && render.$$typeof === REACT_MEMO_TYPE) { - error( - "forwardRef requires a render function but received a `memo` " + - "component. Instead of forwardRef(memo(...)), use " + - "memo(forwardRef(...))." - ); - } else if (typeof render !== "function") { - error( - "forwardRef requires a render function but was given %s.", - render === null ? "null" : typeof render - ); - } else { - if (render.length !== 0 && render.length !== 2) { - error( - "forwardRef render functions accept exactly two parameters: props and ref. %s", - render.length === 1 - ? "Did you forget to use the ref parameter?" - : "Any additional parameter will be undefined." - ); + { + context._currentRenderer = null; + context._currentRenderer2 = null; } + + return context; } - if (render != null) { - if (render.defaultProps != null || render.propTypes != null) { - error( - "forwardRef render functions do not support propTypes or defaultProps. " + - "Did you accidentally pass a React component?" + var Uninitialized = -1; + var Pending = 0; + var Resolved = 1; + var Rejected = 2; + + function lazyInitializer(payload) { + if (payload._status === Uninitialized) { + var ctor = payload._result; + var thenable = ctor(); // Transition to the next state. + // This might throw either because it's missing or throws. If so, we treat it + // as still uninitialized and try again next time. Which is the same as what + // happens if the ctor or any wrappers processing the ctor throws. This might + // end up fixing it if the resolution was a concurrency bug. + + thenable.then( + function (moduleObject) { + if ( + payload._status === Pending || + payload._status === Uninitialized + ) { + // Transition to the next state. + var resolved = payload; + resolved._status = Resolved; + resolved._result = moduleObject; + } + }, + function (error) { + if ( + payload._status === Pending || + payload._status === Uninitialized + ) { + // Transition to the next state. + var rejected = payload; + rejected._status = Rejected; + rejected._result = error; + } + } ); - } - } - } - - var elementType = { - $$typeof: REACT_FORWARD_REF_TYPE, - render: render - }; - - { - var ownName; - Object.defineProperty(elementType, "displayName", { - enumerable: false, - configurable: true, - get: function () { - return ownName; - }, - set: function (name) { - ownName = name; // The inner component shouldn't inherit this display name in most cases, - // because the component may be used elsewhere. - // But it's nice for anonymous functions to inherit the name, - // so that our component-stack generation logic will display their frames. - // An anonymous function generally suggests a pattern like: - // React.forwardRef((props, ref) => {...}); - // This kind of inner function is not used elsewhere so the side effect is okay. - - if (!render.name && !render.displayName) { - render.displayName = name; + + if (payload._status === Uninitialized) { + // In case, we're still uninitialized, then we're waiting for the thenable + // to resolve. Set it as pending in the meantime. + var pending = payload; + pending._status = Pending; + pending._result = thenable; } } - }); - } - return elementType; -} - -var REACT_CLIENT_REFERENCE$2 = Symbol.for("react.client.reference"); -function isValidElementType(type) { - if (typeof type === "string" || typeof type === "function") { - return true; - } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill). - - if ( - type === REACT_FRAGMENT_TYPE || - type === REACT_PROFILER_TYPE || - (enableDebugTracing && type === REACT_DEBUG_TRACING_MODE_TYPE) || - type === REACT_STRICT_MODE_TYPE || - type === REACT_SUSPENSE_TYPE || - type === REACT_SUSPENSE_LIST_TYPE || - type === REACT_LEGACY_HIDDEN_TYPE || - type === REACT_OFFSCREEN_TYPE || - type === REACT_SCOPE_TYPE || - type === REACT_CACHE_TYPE || - (enableTransitionTracing && type === REACT_TRACING_MARKER_TYPE) - ) { - return true; - } - - if (typeof type === "object" && type !== null) { - if ( - type.$$typeof === REACT_LAZY_TYPE || - type.$$typeof === REACT_MEMO_TYPE || - type.$$typeof === REACT_PROVIDER_TYPE || - type.$$typeof === REACT_CONTEXT_TYPE || - type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object - // types supported by any Flight configuration anywhere since - // we don't know which Flight build this will end up being used - // with. - type.$$typeof === REACT_CLIENT_REFERENCE$2 || - type.getModuleId !== undefined - ) { - return true; - } - } + if (payload._status === Resolved) { + var moduleObject = payload._result; - return false; -} + { + if (moduleObject === undefined) { + error( + "lazy: Expected the result of a dynamic imp" + + "ort() call. " + + "Instead received: %s\n\nYour code should look like: \n " + // Break up imports to avoid accidentally parsing them as dependencies. + "const MyComponent = lazy(() => imp" + + "ort('./MyComponent'))\n\n" + + "Did you accidentally put curly braces around the import?", + moduleObject + ); + } + } -function memo(type, compare) { - { - if (!isValidElementType(type)) { - error( - "memo: The first argument must be a component. Instead " + - "received: %s", - type === null ? "null" : typeof type - ); - } - } - - var elementType = { - $$typeof: REACT_MEMO_TYPE, - type: type, - compare: compare === undefined ? null : compare - }; - - { - var ownName; - Object.defineProperty(elementType, "displayName", { - enumerable: false, - configurable: true, - get: function () { - return ownName; - }, - set: function (name) { - ownName = name; // The inner component shouldn't inherit this display name in most cases, - // because the component may be used elsewhere. - // But it's nice for anonymous functions to inherit the name, - // so that our component-stack generation logic will display their frames. - // An anonymous function generally suggests a pattern like: - // React.memo((props) => {...}); - // This kind of inner function is not used elsewhere so the side effect is okay. - - if (!type.name && !type.displayName) { - type.displayName = name; + { + if (!("default" in moduleObject)) { + error( + "lazy: Expected the result of a dynamic imp" + + "ort() call. " + + "Instead received: %s\n\nYour code should look like: \n " + // Break up imports to avoid accidentally parsing them as dependencies. + "const MyComponent = lazy(() => imp" + + "ort('./MyComponent'))", + moduleObject + ); + } } + + return moduleObject.default; + } else { + throw payload._result; } - }); - } + } - return elementType; -} + function lazy(ctor) { + var payload = { + // We use these fields to store the result. + _status: Uninitialized, + _result: ctor + }; + var lazyType = { + $$typeof: REACT_LAZY_TYPE, + _payload: payload, + _init: lazyInitializer + }; -/** - * Keeps track of the current Cache dispatcher. - */ -var ReactCurrentCache = { - current: null -}; + { + // In production, this would just set it on the object. + var defaultProps; + var propTypes; // $FlowFixMe[prop-missing] + + Object.defineProperties(lazyType, { + defaultProps: { + configurable: true, + get: function () { + return defaultProps; + }, + // $FlowFixMe[missing-local-annot] + set: function (newDefaultProps) { + error( + "React.lazy(...): It is not supported to assign `defaultProps` to " + + "a lazy component import. Either specify them where the component " + + "is defined, or create a wrapping component around it." + ); -var UNTERMINATED = 0; -var TERMINATED = 1; -var ERRORED = 2; + defaultProps = newDefaultProps; // Match production behavior more closely: + // $FlowFixMe[prop-missing] -function createCacheRoot() { - return new WeakMap(); -} + Object.defineProperty(lazyType, "defaultProps", { + enumerable: true + }); + } + }, + propTypes: { + configurable: true, + get: function () { + return propTypes; + }, + // $FlowFixMe[missing-local-annot] + set: function (newPropTypes) { + error( + "React.lazy(...): It is not supported to assign `propTypes` to " + + "a lazy component import. Either specify them where the component " + + "is defined, or create a wrapping component around it." + ); -function createCacheNode() { - return { - s: UNTERMINATED, - // status, represents whether the cached computation returned a value or threw an error - v: undefined, - // value, either the cached result or an error, depending on s - o: null, - // object cache, a WeakMap where non-primitive arguments are stored - p: null // primitive cache, a regular Map where primitive arguments are stored. - }; -} + propTypes = newPropTypes; // Match production behavior more closely: + // $FlowFixMe[prop-missing] -function cache(fn) { - return function () { - var dispatcher = ReactCurrentCache.current; + Object.defineProperty(lazyType, "propTypes", { + enumerable: true + }); + } + } + }); + } - if (!dispatcher) { - // If there is no dispatcher, then we treat this as not being cached. - // $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code. - return fn.apply(null, arguments); + return lazyType; } - var fnMap = dispatcher.getCacheForType(createCacheRoot); - var fnNode = fnMap.get(fn); - var cacheNode; + function forwardRef(render) { + { + if (render != null && render.$$typeof === REACT_MEMO_TYPE) { + error( + "forwardRef requires a render function but received a `memo` " + + "component. Instead of forwardRef(memo(...)), use " + + "memo(forwardRef(...))." + ); + } else if (typeof render !== "function") { + error( + "forwardRef requires a render function but was given %s.", + render === null ? "null" : typeof render + ); + } else { + if (render.length !== 0 && render.length !== 2) { + error( + "forwardRef render functions accept exactly two parameters: props and ref. %s", + render.length === 1 + ? "Did you forget to use the ref parameter?" + : "Any additional parameter will be undefined." + ); + } + } + + if (render != null) { + if (render.defaultProps != null || render.propTypes != null) { + error( + "forwardRef render functions do not support propTypes or defaultProps. " + + "Did you accidentally pass a React component?" + ); + } + } + } + + var elementType = { + $$typeof: REACT_FORWARD_REF_TYPE, + render: render + }; + + { + var ownName; + Object.defineProperty(elementType, "displayName", { + enumerable: false, + configurable: true, + get: function () { + return ownName; + }, + set: function (name) { + ownName = name; // The inner component shouldn't inherit this display name in most cases, + // because the component may be used elsewhere. + // But it's nice for anonymous functions to inherit the name, + // so that our component-stack generation logic will display their frames. + // An anonymous function generally suggests a pattern like: + // React.forwardRef((props, ref) => {...}); + // This kind of inner function is not used elsewhere so the side effect is okay. + + if (!render.name && !render.displayName) { + render.displayName = name; + } + } + }); + } - if (fnNode === undefined) { - cacheNode = createCacheNode(); - fnMap.set(fn, cacheNode); - } else { - cacheNode = fnNode; + return elementType; } - for (var i = 0, l = arguments.length; i < l; i++) { - var arg = arguments[i]; + var REACT_CLIENT_REFERENCE$2 = Symbol.for("react.client.reference"); + function isValidElementType(type) { + if (typeof type === "string" || typeof type === "function") { + return true; + } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill). if ( - typeof arg === "function" || - (typeof arg === "object" && arg !== null) + type === REACT_FRAGMENT_TYPE || + type === REACT_PROFILER_TYPE || + (enableDebugTracing && type === REACT_DEBUG_TRACING_MODE_TYPE) || + type === REACT_STRICT_MODE_TYPE || + type === REACT_SUSPENSE_TYPE || + type === REACT_SUSPENSE_LIST_TYPE || + type === REACT_LEGACY_HIDDEN_TYPE || + type === REACT_OFFSCREEN_TYPE || + type === REACT_SCOPE_TYPE || + type === REACT_CACHE_TYPE || + (enableTransitionTracing && type === REACT_TRACING_MARKER_TYPE) ) { - // Objects go into a WeakMap - var objectCache = cacheNode.o; + return true; + } - if (objectCache === null) { - cacheNode.o = objectCache = new WeakMap(); + if (typeof type === "object" && type !== null) { + if ( + type.$$typeof === REACT_LAZY_TYPE || + type.$$typeof === REACT_MEMO_TYPE || + type.$$typeof === REACT_PROVIDER_TYPE || + type.$$typeof === REACT_CONTEXT_TYPE || + type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object + // types supported by any Flight configuration anywhere since + // we don't know which Flight build this will end up being used + // with. + type.$$typeof === REACT_CLIENT_REFERENCE$2 || + type.getModuleId !== undefined + ) { + return true; } + } - var objectNode = objectCache.get(arg); - - if (objectNode === undefined) { - cacheNode = createCacheNode(); - objectCache.set(arg, cacheNode); - } else { - cacheNode = objectNode; - } - } else { - // Primitives go into a regular Map - var primitiveCache = cacheNode.p; + return false; + } - if (primitiveCache === null) { - cacheNode.p = primitiveCache = new Map(); + function memo(type, compare) { + { + if (!isValidElementType(type)) { + error( + "memo: The first argument must be a component. Instead " + + "received: %s", + type === null ? "null" : typeof type + ); } + } - var primitiveNode = primitiveCache.get(arg); + var elementType = { + $$typeof: REACT_MEMO_TYPE, + type: type, + compare: compare === undefined ? null : compare + }; - if (primitiveNode === undefined) { - cacheNode = createCacheNode(); - primitiveCache.set(arg, cacheNode); - } else { - cacheNode = primitiveNode; - } + { + var ownName; + Object.defineProperty(elementType, "displayName", { + enumerable: false, + configurable: true, + get: function () { + return ownName; + }, + set: function (name) { + ownName = name; // The inner component shouldn't inherit this display name in most cases, + // because the component may be used elsewhere. + // But it's nice for anonymous functions to inherit the name, + // so that our component-stack generation logic will display their frames. + // An anonymous function generally suggests a pattern like: + // React.memo((props) => {...}); + // This kind of inner function is not used elsewhere so the side effect is okay. + + if (!type.name && !type.displayName) { + type.displayName = name; + } + } + }); } - } - if (cacheNode.s === TERMINATED) { - return cacheNode.v; + return elementType; } - if (cacheNode.s === ERRORED) { - throw cacheNode.v; - } + /** + * Keeps track of the current Cache dispatcher. + */ + var ReactCurrentCache = { + current: null + }; - try { - // $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code. - var result = fn.apply(null, arguments); - var terminatedNode = cacheNode; - terminatedNode.s = TERMINATED; - terminatedNode.v = result; - return result; - } catch (error) { - // We store the first error that's thrown and rethrow it. - var erroredNode = cacheNode; - erroredNode.s = ERRORED; - erroredNode.v = error; - throw error; + var UNTERMINATED = 0; + var TERMINATED = 1; + var ERRORED = 2; + + function createCacheRoot() { + return new WeakMap(); } - }; -} -/** - * Keeps track of the current dispatcher. - */ -var ReactCurrentDispatcher$1 = { - current: null -}; - -function resolveDispatcher() { - var dispatcher = ReactCurrentDispatcher$1.current; - - { - if (dispatcher === null) { - 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." - ); + function createCacheNode() { + return { + s: UNTERMINATED, + // status, represents whether the cached computation returned a value or threw an error + v: undefined, + // value, either the cached result or an error, depending on s + o: null, + // object cache, a WeakMap where non-primitive arguments are stored + p: null // primitive cache, a regular Map where primitive arguments are stored. + }; } - } // Will result in a null access error if accessed outside render phase. We - // intentionally don't throw our own error because this is in a hot path. - // Also helps ensure this is inlined. - return dispatcher; -} + function cache(fn) { + return function () { + var dispatcher = ReactCurrentCache.current; + + if (!dispatcher) { + // If there is no dispatcher, then we treat this as not being cached. + // $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code. + return fn.apply(null, arguments); + } + + var fnMap = dispatcher.getCacheForType(createCacheRoot); + var fnNode = fnMap.get(fn); + var cacheNode; + + if (fnNode === undefined) { + cacheNode = createCacheNode(); + fnMap.set(fn, cacheNode); + } else { + cacheNode = fnNode; + } -function getCacheSignal() { - var dispatcher = ReactCurrentCache.current; - - if (!dispatcher) { - // If we have no cache to associate with this call, then we don't know - // its lifetime. We abort early since that's safer than letting it live - // for ever. Unlike just caching which can be a functional noop outside - // of React, these should generally always be associated with some React - // render but we're not limiting quite as much as making it a Hook. - // It's safer than erroring early at runtime. - var controller = new AbortController(); - var reason = new Error( - "This CacheSignal was requested outside React which means that it is " + - "immediately aborted." - ); - controller.abort(reason); - return controller.signal; - } - - return dispatcher.getCacheSignal(); -} -function getCacheForType(resourceType) { - var dispatcher = ReactCurrentCache.current; + for (var i = 0, l = arguments.length; i < l; i++) { + var arg = arguments[i]; - if (!dispatcher) { - // If there is no dispatcher, then we treat this as not being cached. - return resourceType(); - } + if ( + typeof arg === "function" || + (typeof arg === "object" && arg !== null) + ) { + // Objects go into a WeakMap + var objectCache = cacheNode.o; - return dispatcher.getCacheForType(resourceType); -} -function useContext(Context) { - var dispatcher = resolveDispatcher(); + if (objectCache === null) { + cacheNode.o = objectCache = new WeakMap(); + } - { - // TODO: add a more generic warning for invalid values. - if (Context._context !== undefined) { - var realContext = Context._context; // Don't deduplicate because this legitimately causes bugs - // and nobody should be using this in existing code. + var objectNode = objectCache.get(arg); - if (realContext.Consumer === Context) { - error( - "Calling useContext(Context.Consumer) is not supported, may cause bugs, and will be " + - "removed in a future major release. Did you mean to call useContext(Context) instead?" - ); - } else if (realContext.Provider === Context) { - error( - "Calling useContext(Context.Provider) is not supported. " + - "Did you mean to call useContext(Context) instead?" - ); - } - } - } + if (objectNode === undefined) { + cacheNode = createCacheNode(); + objectCache.set(arg, cacheNode); + } else { + cacheNode = objectNode; + } + } else { + // Primitives go into a regular Map + var primitiveCache = cacheNode.p; - return dispatcher.useContext(Context); -} -function useState(initialState) { - var dispatcher = resolveDispatcher(); - return dispatcher.useState(initialState); -} -function useReducer(reducer, initialArg, init) { - var dispatcher = resolveDispatcher(); - return dispatcher.useReducer(reducer, initialArg, init); -} -function useRef(initialValue) { - var dispatcher = resolveDispatcher(); - return dispatcher.useRef(initialValue); -} -function useEffect(create, deps) { - var dispatcher = resolveDispatcher(); - return dispatcher.useEffect(create, deps); -} -function useInsertionEffect(create, deps) { - var dispatcher = resolveDispatcher(); - return dispatcher.useInsertionEffect(create, deps); -} -function useLayoutEffect(create, deps) { - var dispatcher = resolveDispatcher(); - return dispatcher.useLayoutEffect(create, deps); -} -function useCallback(callback, deps) { - var dispatcher = resolveDispatcher(); - return dispatcher.useCallback(callback, deps); -} -function useMemo(create, deps) { - var dispatcher = resolveDispatcher(); - return dispatcher.useMemo(create, deps); -} -function useImperativeHandle(ref, create, deps) { - var dispatcher = resolveDispatcher(); - return dispatcher.useImperativeHandle(ref, create, deps); -} -function useDebugValue(value, formatterFn) { - { - var dispatcher = resolveDispatcher(); - return dispatcher.useDebugValue(value, formatterFn); - } -} -function useTransition() { - var dispatcher = resolveDispatcher(); - return dispatcher.useTransition(); -} -function useDeferredValue(value, initialValue) { - var dispatcher = resolveDispatcher(); - return dispatcher.useDeferredValue(value, initialValue); -} -function useId() { - var dispatcher = resolveDispatcher(); - return dispatcher.useId(); -} -function useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { - var dispatcher = resolveDispatcher(); - return dispatcher.useSyncExternalStore( - subscribe, - getSnapshot, - getServerSnapshot - ); -} -function useCacheRefresh() { - var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional + if (primitiveCache === null) { + cacheNode.p = primitiveCache = new Map(); + } - return dispatcher.useCacheRefresh(); -} -function use(usable) { - var dispatcher = resolveDispatcher(); - return dispatcher.use(usable); -} -function useMemoCache(size) { - var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional + var primitiveNode = primitiveCache.get(arg); - return dispatcher.useMemoCache(size); -} -function useEffectEvent(callback) { - var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional + if (primitiveNode === undefined) { + cacheNode = createCacheNode(); + primitiveCache.set(arg, cacheNode); + } else { + cacheNode = primitiveNode; + } + } + } - return dispatcher.useEffectEvent(callback); -} -function useOptimistic(passthrough, reducer) { - var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional + if (cacheNode.s === TERMINATED) { + return cacheNode.v; + } - return dispatcher.useOptimistic(passthrough, reducer); -} + if (cacheNode.s === ERRORED) { + throw cacheNode.v; + } -// Helpers to patch console.logs to avoid logging during side-effect free -// replaying on render function. This currently only patches the object -// lazily which won't cover if the log function was extracted eagerly. -// We could also eagerly patch the method. -var disabledDepth = 0; -var prevLog; -var prevInfo; -var prevWarn; -var prevError; -var prevGroup; -var prevGroupCollapsed; -var prevGroupEnd; - -function disabledLog() {} - -disabledLog.__reactDisabledLog = true; -function disableLogs() { - { - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - prevLog = console.log; - prevInfo = console.info; - prevWarn = console.warn; - prevError = console.error; - prevGroup = console.group; - prevGroupCollapsed = console.groupCollapsed; - prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 - - var props = { - configurable: true, - enumerable: true, - value: disabledLog, - writable: true - }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. - - Object.defineProperties(console, { - info: props, - log: props, - warn: props, - error: props, - group: props, - groupCollapsed: props, - groupEnd: props - }); - /* eslint-enable react-internal/no-production-logging */ + try { + // $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code. + var result = fn.apply(null, arguments); + var terminatedNode = cacheNode; + terminatedNode.s = TERMINATED; + terminatedNode.v = result; + return result; + } catch (error) { + // We store the first error that's thrown and rethrow it. + var erroredNode = cacheNode; + erroredNode.s = ERRORED; + erroredNode.v = error; + throw error; + } + }; } - disabledDepth++; - } -} -function reenableLogs() { - { - disabledDepth--; - - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - var props = { - configurable: true, - enumerable: true, - writable: true - }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. - - Object.defineProperties(console, { - log: assign({}, props, { - value: prevLog - }), - info: assign({}, props, { - value: prevInfo - }), - warn: assign({}, props, { - value: prevWarn - }), - error: assign({}, props, { - value: prevError - }), - group: assign({}, props, { - value: prevGroup - }), - groupCollapsed: assign({}, props, { - value: prevGroupCollapsed - }), - groupEnd: assign({}, props, { - value: prevGroupEnd - }) - }); - /* eslint-enable react-internal/no-production-logging */ - } + /** + * Keeps track of the current dispatcher. + */ + var ReactCurrentDispatcher$1 = { + current: null + }; - if (disabledDepth < 0) { - error( - "disabledDepth fell below zero. " + - "This is a bug in React. Please file an issue." - ); - } - } -} + function resolveDispatcher() { + var dispatcher = ReactCurrentDispatcher$1.current; -/** - * Keeps track of the current batch's configuration such as how long an update - * should suspend for if it needs to. - */ -var ReactCurrentBatchConfig = { - transition: null -}; - -var ReactCurrentActQueue = { - current: null, - // Used to reproduce behavior of `batchedUpdates` in legacy mode. - isBatchingLegacy: false, - didScheduleLegacyUpdate: false, - // Tracks whether something called `use` during the current batch of work. - // Determines whether we should yield to microtasks to unwrap already resolved - // promises without suspending. - didUsePromise: false -}; - -var ReactDebugCurrentFrame$2 = {}; -var currentExtraStackFrame = null; -function setExtraStackFrame(stack) { - { - currentExtraStackFrame = stack; - } -} + { + if (dispatcher === null) { + 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." + ); + } + } // Will result in a null access error if accessed outside render phase. We + // intentionally don't throw our own error because this is in a hot path. + // Also helps ensure this is inlined. -{ - ReactDebugCurrentFrame$2.setExtraStackFrame = function (stack) { - { - currentExtraStackFrame = stack; + return dispatcher; } - }; // Stack implementation injected by the current renderer. - - ReactDebugCurrentFrame$2.getCurrentStack = null; - ReactDebugCurrentFrame$2.getStackAddendum = function () { - var stack = ""; // Add an extra top frame while an element is being validated - - if (currentExtraStackFrame) { - stack += currentExtraStackFrame; - } // Delegate to the injected renderer-specific implementation - - var impl = ReactDebugCurrentFrame$2.getCurrentStack; + function getCacheSignal() { + var dispatcher = ReactCurrentCache.current; + + if (!dispatcher) { + // If we have no cache to associate with this call, then we don't know + // its lifetime. We abort early since that's safer than letting it live + // for ever. Unlike just caching which can be a functional noop outside + // of React, these should generally always be associated with some React + // render but we're not limiting quite as much as making it a Hook. + // It's safer than erroring early at runtime. + var controller = new AbortController(); + var reason = new Error( + "This CacheSignal was requested outside React which means that it is " + + "immediately aborted." + ); + controller.abort(reason); + return controller.signal; + } - if (impl) { - stack += impl() || ""; + return dispatcher.getCacheSignal(); } + function getCacheForType(resourceType) { + var dispatcher = ReactCurrentCache.current; - return stack; - }; -} + if (!dispatcher) { + // If there is no dispatcher, then we treat this as not being cached. + return resourceType(); + } -var ReactSharedInternals = { - ReactCurrentDispatcher: ReactCurrentDispatcher$1, - ReactCurrentCache: ReactCurrentCache, - ReactCurrentBatchConfig: ReactCurrentBatchConfig, - ReactCurrentOwner: ReactCurrentOwner$2 -}; + return dispatcher.getCacheForType(resourceType); + } + function useContext(Context) { + var dispatcher = resolveDispatcher(); -{ - ReactSharedInternals.ReactDebugCurrentFrame = ReactDebugCurrentFrame$2; - ReactSharedInternals.ReactCurrentActQueue = ReactCurrentActQueue; -} + { + // TODO: add a more generic warning for invalid values. + if (Context._context !== undefined) { + var realContext = Context._context; // Don't deduplicate because this legitimately causes bugs + // and nobody should be using this in existing code. -var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; -var prefix; -function describeBuiltInComponentFrame(name, source, ownerFn) { - { - if (prefix === undefined) { - // Extract the VM specific prefix used by each line. - try { - throw Error(); - } catch (x) { - var match = x.stack.trim().match(/\n( *(at )?)/); - prefix = (match && match[1]) || ""; + if (realContext.Consumer === Context) { + error( + "Calling useContext(Context.Consumer) is not supported, may cause bugs, and will be " + + "removed in a future major release. Did you mean to call useContext(Context) instead?" + ); + } else if (realContext.Provider === Context) { + error( + "Calling useContext(Context.Provider) is not supported. " + + "Did you mean to call useContext(Context) instead?" + ); + } + } } - } // We use the prefix to ensure our stacks line up with native stack frames. - return "\n" + prefix + name; - } -} -var reentry = false; -var componentFrameCache; + return dispatcher.useContext(Context); + } + function useState(initialState) { + var dispatcher = resolveDispatcher(); + return dispatcher.useState(initialState); + } + function useReducer(reducer, initialArg, init) { + var dispatcher = resolveDispatcher(); + return dispatcher.useReducer(reducer, initialArg, init); + } + function useRef(initialValue) { + var dispatcher = resolveDispatcher(); + return dispatcher.useRef(initialValue); + } + function useEffect(create, deps) { + var dispatcher = resolveDispatcher(); + return dispatcher.useEffect(create, deps); + } + function useInsertionEffect(create, deps) { + var dispatcher = resolveDispatcher(); + return dispatcher.useInsertionEffect(create, deps); + } + function useLayoutEffect(create, deps) { + var dispatcher = resolveDispatcher(); + return dispatcher.useLayoutEffect(create, deps); + } + function useCallback(callback, deps) { + var dispatcher = resolveDispatcher(); + return dispatcher.useCallback(callback, deps); + } + function useMemo(create, deps) { + var dispatcher = resolveDispatcher(); + return dispatcher.useMemo(create, deps); + } + function useImperativeHandle(ref, create, deps) { + var dispatcher = resolveDispatcher(); + return dispatcher.useImperativeHandle(ref, create, deps); + } + function useDebugValue(value, formatterFn) { + { + var dispatcher = resolveDispatcher(); + return dispatcher.useDebugValue(value, formatterFn); + } + } + function useTransition() { + var dispatcher = resolveDispatcher(); + return dispatcher.useTransition(); + } + function useDeferredValue(value, initialValue) { + var dispatcher = resolveDispatcher(); + return dispatcher.useDeferredValue(value, initialValue); + } + function useId() { + var dispatcher = resolveDispatcher(); + return dispatcher.useId(); + } + function useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { + var dispatcher = resolveDispatcher(); + return dispatcher.useSyncExternalStore( + subscribe, + getSnapshot, + getServerSnapshot + ); + } + function useCacheRefresh() { + var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional -{ - var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; - componentFrameCache = new PossiblyWeakMap(); -} + return dispatcher.useCacheRefresh(); + } + function use(usable) { + var dispatcher = resolveDispatcher(); + return dispatcher.use(usable); + } + function useMemoCache(size) { + var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional -function describeNativeComponentFrame(fn, construct) { - // If something asked for a stack inside a fake render, it should get ignored. - if (!fn || reentry) { - return ""; - } + return dispatcher.useMemoCache(size); + } + function useEffectEvent(callback) { + var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional - { - var frame = componentFrameCache.get(fn); + return dispatcher.useEffectEvent(callback); + } + function useOptimistic(passthrough, reducer) { + var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional - if (frame !== undefined) { - return frame; + return dispatcher.useOptimistic(passthrough, reducer); } - } - - var control; - reentry = true; - var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. - - Error.prepareStackTrace = undefined; - var previousDispatcher; - - { - previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function - // for warnings. - - ReactCurrentDispatcher.current = null; - disableLogs(); - } - - try { - // This should throw. - if (construct) { - // Something should be setting the props in the constructor. - var Fake = function () { - throw Error(); - }; // $FlowFixMe[prop-missing] - - Object.defineProperty(Fake.prototype, "props", { - set: function () { - // We use a throwing setter instead of frozen or non-writable props - // because that won't throw in a non-strict mode function. - throw Error(); - } - }); - if (typeof Reflect === "object" && Reflect.construct) { - // We construct a different control for this case to include any extra - // frames added by the construct call. - try { - Reflect.construct(Fake, []); - } catch (x) { - control = x; + // Helpers to patch console.logs to avoid logging during side-effect free + // replaying on render function. This currently only patches the object + // lazily which won't cover if the log function was extracted eagerly. + // We could also eagerly patch the method. + var disabledDepth = 0; + var prevLog; + var prevInfo; + var prevWarn; + var prevError; + var prevGroup; + var prevGroupCollapsed; + var prevGroupEnd; + + function disabledLog() {} + + disabledLog.__reactDisabledLog = true; + function disableLogs() { + { + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + prevLog = console.log; + prevInfo = console.info; + prevWarn = console.warn; + prevError = console.error; + prevGroup = console.group; + prevGroupCollapsed = console.groupCollapsed; + prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 + + var props = { + configurable: true, + enumerable: true, + value: disabledLog, + writable: true + }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. + + Object.defineProperties(console, { + info: props, + log: props, + warn: props, + error: props, + group: props, + groupCollapsed: props, + groupEnd: props + }); + /* eslint-enable react-internal/no-production-logging */ } - Reflect.construct(fn, [], Fake); - } else { - try { - Fake.call(); - } catch (x) { - control = x; - } // $FlowFixMe[prop-missing] found when upgrading Flow - - fn.call(Fake.prototype); - } - } else { - try { - throw Error(); - } catch (x) { - control = x; - } // TODO(luna): This will currently only throw if the function component - // tries to access React/ReactDOM/props. We should probably make this throw - // in simple components too - - var maybePromise = fn(); // If the function component returns a promise, it's likely an async - // component, which we don't yet support. Attach a noop catch handler to - // silence the error. - // TODO: Implement component stacks for async client components? - - if (maybePromise && typeof maybePromise.catch === "function") { - maybePromise.catch(function () {}); + disabledDepth++; } } - } catch (sample) { - // This is inlined manually because closure doesn't do it for us. - if (sample && control && typeof sample.stack === "string") { - // This extracts the first frame from the sample that isn't also in the control. - // Skipping one frame that we assume is the frame that calls the two. - var sampleLines = sample.stack.split("\n"); - var controlLines = control.stack.split("\n"); - var s = sampleLines.length - 1; - var c = controlLines.length - 1; - - while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { - // We expect at least one stack frame to be shared. - // Typically this will be the root most one. However, stack frames may be - // cut off due to maximum stack limits. In this case, one maybe cut off - // earlier than the other. We assume that the sample is longer or the same - // and there for cut off earlier. So we should find the root most frame in - // the sample somewhere in the control. - c--; - } + function reenableLogs() { + { + disabledDepth--; + + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + var props = { + configurable: true, + enumerable: true, + writable: true + }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. + + Object.defineProperties(console, { + log: assign({}, props, { + value: prevLog + }), + info: assign({}, props, { + value: prevInfo + }), + warn: assign({}, props, { + value: prevWarn + }), + error: assign({}, props, { + value: prevError + }), + group: assign({}, props, { + value: prevGroup + }), + groupCollapsed: assign({}, props, { + value: prevGroupCollapsed + }), + groupEnd: assign({}, props, { + value: prevGroupEnd + }) + }); + /* eslint-enable react-internal/no-production-logging */ + } - for (; s >= 1 && c >= 0; s--, c--) { - // Next we find the first one that isn't the same which should be the - // frame that called our sample function and the control. - if (sampleLines[s] !== controlLines[c]) { - // In V8, the first line is describing the message but other VMs don't. - // If we're about to return the first line, and the control is also on the same - // line, that's a pretty good indicator that our sample threw at same line as - // the control. I.e. before we entered the sample frame. So we ignore this result. - // This can happen if you passed a class to function component, or non-function. - if (s !== 1 || c !== 1) { - do { - s--; - c--; // We may still have similar intermediate frames from the construct call. - // The next one that isn't the same should be our match though. - - if (c < 0 || sampleLines[s] !== controlLines[c]) { - // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. - var _frame = "\n" + sampleLines[s].replace(" at new ", " at "); // If our component frame is labeled "" - // but we have a user-provided "displayName" - // splice it in to make the stack more readable. - - if (fn.displayName && _frame.includes("")) { - _frame = _frame.replace("", fn.displayName); - } + if (disabledDepth < 0) { + error( + "disabledDepth fell below zero. " + + "This is a bug in React. Please file an issue." + ); + } + } + } - { - if (typeof fn === "function") { - componentFrameCache.set(fn, _frame); - } - } // Return the line we found. + /** + * Keeps track of the current batch's configuration such as how long an update + * should suspend for if it needs to. + */ + var ReactCurrentBatchConfig = { + transition: null + }; - return _frame; - } - } while (s >= 1 && c >= 0); - } + var ReactCurrentActQueue = { + current: null, + // Used to reproduce behavior of `batchedUpdates` in legacy mode. + isBatchingLegacy: false, + didScheduleLegacyUpdate: false, + // Tracks whether something called `use` during the current batch of work. + // Determines whether we should yield to microtasks to unwrap already resolved + // promises without suspending. + didUsePromise: false + }; - break; - } + var ReactDebugCurrentFrame$2 = {}; + var currentExtraStackFrame = null; + function setExtraStackFrame(stack) { + { + currentExtraStackFrame = stack; } } - } finally { - reentry = false; { - ReactCurrentDispatcher.current = previousDispatcher; - reenableLogs(); - } + ReactDebugCurrentFrame$2.setExtraStackFrame = function (stack) { + { + currentExtraStackFrame = stack; + } + }; // Stack implementation injected by the current renderer. - Error.prepareStackTrace = previousPrepareStackTrace; - } // Fallback to just using the name if we couldn't make it throw. + ReactDebugCurrentFrame$2.getCurrentStack = null; - var name = fn ? fn.displayName || fn.name : ""; - var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ""; + ReactDebugCurrentFrame$2.getStackAddendum = function () { + var stack = ""; // Add an extra top frame while an element is being validated - { - if (typeof fn === "function") { - componentFrameCache.set(fn, syntheticFrame); - } - } + if (currentExtraStackFrame) { + stack += currentExtraStackFrame; + } // Delegate to the injected renderer-specific implementation - return syntheticFrame; -} -function describeFunctionComponentFrame(fn, source, ownerFn) { - { - return describeNativeComponentFrame(fn, false); - } -} + var impl = ReactDebugCurrentFrame$2.getCurrentStack; -function shouldConstruct(Component) { - var prototype = Component.prototype; - return !!(prototype && prototype.isReactComponent); -} + if (impl) { + stack += impl() || ""; + } + + return stack; + }; + } -function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { - if (type == null) { - return ""; - } + var ReactSharedInternals = { + ReactCurrentDispatcher: ReactCurrentDispatcher$1, + ReactCurrentCache: ReactCurrentCache, + ReactCurrentBatchConfig: ReactCurrentBatchConfig, + ReactCurrentOwner: ReactCurrentOwner$2 + }; - if (typeof type === "function") { { - return describeNativeComponentFrame(type, shouldConstruct(type)); + ReactSharedInternals.ReactDebugCurrentFrame = ReactDebugCurrentFrame$2; + ReactSharedInternals.ReactCurrentActQueue = ReactCurrentActQueue; } - } - - if (typeof type === "string") { - return describeBuiltInComponentFrame(type); - } - switch (type) { - case REACT_SUSPENSE_TYPE: - return describeBuiltInComponentFrame("Suspense"); + var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; + var prefix; + function describeBuiltInComponentFrame(name, source, ownerFn) { + { + if (prefix === undefined) { + // Extract the VM specific prefix used by each line. + try { + throw Error(); + } catch (x) { + var match = x.stack.trim().match(/\n( *(at )?)/); + prefix = (match && match[1]) || ""; + } + } // We use the prefix to ensure our stacks line up with native stack frames. - case REACT_SUSPENSE_LIST_TYPE: - return describeBuiltInComponentFrame("SuspenseList"); - } + return "\n" + prefix + name; + } + } + var reentry = false; + var componentFrameCache; - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_FORWARD_REF_TYPE: - return describeFunctionComponentFrame(type.render); + { + var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; + componentFrameCache = new PossiblyWeakMap(); + } - case REACT_MEMO_TYPE: - // Memo may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); + function describeNativeComponentFrame(fn, construct) { + // If something asked for a stack inside a fake render, it should get ignored. + if (!fn || reentry) { + return ""; + } - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + { + var frame = componentFrameCache.get(fn); - try { - // Lazy may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV( - init(payload), - source, - ownerFn - ); - } catch (x) {} + if (frame !== undefined) { + return frame; + } } - } - } - return ""; -} + var control; + reentry = true; + var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. -var loggedTypeFailures = {}; -var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; + Error.prepareStackTrace = undefined; + var previousDispatcher; -function setCurrentlyValidatingElement$2(element) { - { - if (element) { - var owner = element._owner; - var stack = describeUnknownElementTypeFrameInDEV( - element.type, - element._source, - owner ? owner.type : null - ); - ReactDebugCurrentFrame$1.setExtraStackFrame(stack); - } else { - ReactDebugCurrentFrame$1.setExtraStackFrame(null); - } - } -} + { + previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function + // for warnings. + + ReactCurrentDispatcher.current = null; + disableLogs(); + } -function checkPropTypes(typeSpecs, values, location, componentName, element) { - { - // $FlowFixMe[incompatible-use] This is okay but Flow doesn't know it. - var has = Function.call.bind(hasOwnProperty); + try { + // This should throw. + if (construct) { + // Something should be setting the props in the constructor. + var Fake = function () { + throw Error(); + }; // $FlowFixMe[prop-missing] + + Object.defineProperty(Fake.prototype, "props", { + set: function () { + // We use a throwing setter instead of frozen or non-writable props + // because that won't throw in a non-strict mode function. + throw Error(); + } + }); - for (var typeSpecName in typeSpecs) { - if (has(typeSpecs, typeSpecName)) { - var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to - // fail the render phase where it didn't fail before. So we log it. - // After these have been cleaned up, we'll let them throw. + if (typeof Reflect === "object" && Reflect.construct) { + // We construct a different control for this case to include any extra + // frames added by the construct call. + try { + Reflect.construct(Fake, []); + } catch (x) { + control = x; + } - try { - // This is intentionally an invariant that gets caught. It's the same - // behavior as without this statement except with a better message. - if (typeof typeSpecs[typeSpecName] !== "function") { - // eslint-disable-next-line react-internal/prod-error-codes - 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`." - ); - err.name = "Invariant Violation"; - throw err; - } + Reflect.construct(fn, [], Fake); + } else { + try { + Fake.call(); + } catch (x) { + control = x; + } // $FlowFixMe[prop-missing] found when upgrading Flow - error$1 = typeSpecs[typeSpecName]( - values, - typeSpecName, - componentName, - location, - null, - "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" - ); - } catch (ex) { - error$1 = ex; + fn.call(Fake.prototype); + } + } else { + try { + throw Error(); + } catch (x) { + control = x; + } // TODO(luna): This will currently only throw if the function component + // tries to access React/ReactDOM/props. We should probably make this throw + // in simple components too + + var maybePromise = fn(); // If the function component returns a promise, it's likely an async + // component, which we don't yet support. Attach a noop catch handler to + // silence the error. + // TODO: Implement component stacks for async client components? + + if (maybePromise && typeof maybePromise.catch === "function") { + maybePromise.catch(function () {}); + } } + } catch (sample) { + // This is inlined manually because closure doesn't do it for us. + if (sample && control && typeof sample.stack === "string") { + // This extracts the first frame from the sample that isn't also in the control. + // Skipping one frame that we assume is the frame that calls the two. + var sampleLines = sample.stack.split("\n"); + var controlLines = control.stack.split("\n"); + var s = sampleLines.length - 1; + var c = controlLines.length - 1; + + while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { + // We expect at least one stack frame to be shared. + // Typically this will be the root most one. However, stack frames may be + // cut off due to maximum stack limits. In this case, one maybe cut off + // earlier than the other. We assume that the sample is longer or the same + // and there for cut off earlier. So we should find the root most frame in + // the sample somewhere in the control. + c--; + } - if (error$1 && !(error$1 instanceof Error)) { - setCurrentlyValidatingElement$2(element); + for (; s >= 1 && c >= 0; s--, c--) { + // Next we find the first one that isn't the same which should be the + // frame that called our sample function and the control. + if (sampleLines[s] !== controlLines[c]) { + // In V8, the first line is describing the message but other VMs don't. + // If we're about to return the first line, and the control is also on the same + // line, that's a pretty good indicator that our sample threw at same line as + // the control. I.e. before we entered the sample frame. So we ignore this result. + // This can happen if you passed a class to function component, or non-function. + if (s !== 1 || c !== 1) { + do { + s--; + c--; // We may still have similar intermediate frames from the construct call. + // The next one that isn't the same should be our match though. + + if (c < 0 || sampleLines[s] !== controlLines[c]) { + // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. + var _frame = + "\n" + sampleLines[s].replace(" at new ", " at "); // If our component frame is labeled "" + // but we have a user-provided "displayName" + // splice it in to make the stack more readable. + + if (fn.displayName && _frame.includes("")) { + _frame = _frame.replace("", fn.displayName); + } + + { + if (typeof fn === "function") { + componentFrameCache.set(fn, _frame); + } + } // Return the line we found. + + return _frame; + } + } while (s >= 1 && c >= 0); + } - 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 - ); + break; + } + } + } + } finally { + reentry = false; - setCurrentlyValidatingElement$2(null); + { + ReactCurrentDispatcher.current = previousDispatcher; + reenableLogs(); } - if ( - error$1 instanceof Error && - !(error$1.message in loggedTypeFailures) - ) { - // Only monitor this failure once because there tends to be a lot of the - // same error. - loggedTypeFailures[error$1.message] = true; - setCurrentlyValidatingElement$2(element); + Error.prepareStackTrace = previousPrepareStackTrace; + } // Fallback to just using the name if we couldn't make it throw. - error("Failed %s type: %s", location, error$1.message); + var name = fn ? fn.displayName || fn.name : ""; + var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ""; - setCurrentlyValidatingElement$2(null); + { + if (typeof fn === "function") { + componentFrameCache.set(fn, syntheticFrame); } } - } - } -} -var REACT_CLIENT_REFERENCE$1 = Symbol.for("react.client.reference"); + return syntheticFrame; + } + function describeFunctionComponentFrame(fn, source, ownerFn) { + { + return describeNativeComponentFrame(fn, false); + } + } -function setCurrentlyValidatingElement$1(element) { - { - if (element) { - var owner = element._owner; - var stack = describeUnknownElementTypeFrameInDEV( - element.type, - element._source, - owner ? owner.type : null - ); - setExtraStackFrame(stack); - } else { - setExtraStackFrame(null); + function shouldConstruct(Component) { + var prototype = Component.prototype; + return !!(prototype && prototype.isReactComponent); } - } -} -var propTypesMisspellWarningShown$1; + function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { + if (type == null) { + return ""; + } -{ - propTypesMisspellWarningShown$1 = false; -} + if (typeof type === "function") { + { + return describeNativeComponentFrame(type, shouldConstruct(type)); + } + } -function getDeclarationErrorAddendum$1() { - if (ReactCurrentOwner$2.current) { - var name = getComponentNameFromType(ReactCurrentOwner$2.current.type); + if (typeof type === "string") { + return describeBuiltInComponentFrame(type); + } - if (name) { - return "\n\nCheck the render method of `" + name + "`."; - } - } + switch (type) { + case REACT_SUSPENSE_TYPE: + return describeBuiltInComponentFrame("Suspense"); - return ""; -} + case REACT_SUSPENSE_LIST_TYPE: + return describeBuiltInComponentFrame("SuspenseList"); + } -function getSourceInfoErrorAddendum$1(source) { - if (source !== undefined) { - var fileName = source.fileName.replace(/^.*[\\\/]/, ""); - var lineNumber = source.lineNumber; - return "\n\nCheck your code at " + fileName + ":" + lineNumber + "."; - } + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_FORWARD_REF_TYPE: + return describeFunctionComponentFrame(type.render); + + case REACT_MEMO_TYPE: + // Memo may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + type.type, + source, + ownerFn + ); - return ""; -} + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; + + try { + // Lazy may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + init(payload), + source, + ownerFn + ); + } catch (x) {} + } + } + } -function getSourceInfoErrorAddendumForProps(elementProps) { - if (elementProps !== null && elementProps !== undefined) { - return getSourceInfoErrorAddendum$1(elementProps.__source); - } + return ""; + } - return ""; -} -/** - * Warn if there's no key explicitly set on dynamic arrays of children or - * object keys are not valid. This allows us to keep track of children between - * updates. - */ + var loggedTypeFailures = {}; + var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; -var ownerHasKeyUseWarning$1 = {}; + function setCurrentlyValidatingElement$2(element) { + { + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV( + element.type, + element._source, + owner ? owner.type : null + ); + ReactDebugCurrentFrame$1.setExtraStackFrame(stack); + } else { + ReactDebugCurrentFrame$1.setExtraStackFrame(null); + } + } + } -function getCurrentComponentErrorInfo$1(parentType) { - var info = getDeclarationErrorAddendum$1(); + function checkPropTypes( + typeSpecs, + values, + location, + componentName, + element + ) { + { + // $FlowFixMe[incompatible-use] This is okay but Flow doesn't know it. + var has = Function.call.bind(hasOwnProperty); + + for (var typeSpecName in typeSpecs) { + if (has(typeSpecs, typeSpecName)) { + var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to + // fail the render phase where it didn't fail before. So we log it. + // After these have been cleaned up, we'll let them throw. + + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + if (typeof typeSpecs[typeSpecName] !== "function") { + // eslint-disable-next-line react-internal/prod-error-codes + 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`." + ); + err.name = "Invariant Violation"; + throw err; + } - if (!info) { - var parentName = - typeof parentType === "string" - ? parentType - : parentType.displayName || parentType.name; + error$1 = typeSpecs[typeSpecName]( + values, + typeSpecName, + componentName, + location, + null, + "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" + ); + } catch (ex) { + error$1 = ex; + } - if (parentName) { - info = "\n\nCheck the top-level render call using <" + parentName + ">."; - } - } + if (error$1 && !(error$1 instanceof Error)) { + setCurrentlyValidatingElement$2(element); - return info; -} -/** - * Warn if the element doesn't have an explicit key assigned to it. - * This element is in an array. The array could grow and shrink or be - * reordered. All children that haven't already been validated are required to - * have a "key" property assigned to it. Error statuses are cached so a warning - * will only be shown once. - * - * @internal - * @param {ReactElement} element Element that requires a key. - * @param {*} parentType element's parent's type. - */ + 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 + ); -function validateExplicitKey$1(element, parentType) { - if (!element._store || element._store.validated || element.key != null) { - return; - } - - element._store.validated = true; - var currentComponentErrorInfo = getCurrentComponentErrorInfo$1(parentType); - - if (ownerHasKeyUseWarning$1[currentComponentErrorInfo]) { - return; - } - - ownerHasKeyUseWarning$1[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a - // property, it may be the creator of the child that's responsible for - // assigning it a key. - - var childOwner = ""; - - if ( - element && - element._owner && - element._owner !== ReactCurrentOwner$2.current - ) { - // Give the component that originally created this child. - childOwner = - " It was passed a child from " + - getComponentNameFromType(element._owner.type) + - "."; - } - - { - setCurrentlyValidatingElement$1(element); - - error( - 'Each child in a list should have a unique "key" prop.' + - "%s%s See https://reactjs.org/link/warning-keys for more information.", - currentComponentErrorInfo, - childOwner - ); - - setCurrentlyValidatingElement$1(null); - } -} -/** - * Ensure that every element either is passed in a static location, in an - * array with an explicit keys property defined, or in an object literal - * with valid key property. - * - * @internal - * @param {ReactNode} node Statically passed child of any type. - * @param {*} parentType node's parent's type. - */ + setCurrentlyValidatingElement$2(null); + } -function validateChildKeys$1(node, parentType) { - if (typeof node !== "object" || !node) { - return; - } + if ( + error$1 instanceof Error && + !(error$1.message in loggedTypeFailures) + ) { + // Only monitor this failure once because there tends to be a lot of the + // same error. + loggedTypeFailures[error$1.message] = true; + setCurrentlyValidatingElement$2(element); - if (node.$$typeof === REACT_CLIENT_REFERENCE$1); - else if (isArray(node)) { - for (var i = 0; i < node.length; i++) { - var child = node[i]; + error("Failed %s type: %s", location, error$1.message); - if (isValidElement$1(child)) { - validateExplicitKey$1(child, parentType); + setCurrentlyValidatingElement$2(null); + } + } + } } } - } else if (isValidElement$1(node)) { - // This element was passed in a valid location. - if (node._store) { - node._store.validated = true; - } - } else { - var iteratorFn = getIteratorFn(node); - - if (typeof iteratorFn === "function") { - // Entry iterators used to provide implicit keys, - // but now we print a separate warning for them later. - if (iteratorFn !== node.entries) { - var iterator = iteratorFn.call(node); - var step; - - while (!(step = iterator.next()).done) { - if (isValidElement$1(step.value)) { - validateExplicitKey$1(step.value, parentType); - } + + var REACT_CLIENT_REFERENCE$1 = Symbol.for("react.client.reference"); + + function setCurrentlyValidatingElement$1(element) { + { + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV( + element.type, + element._source, + owner ? owner.type : null + ); + setExtraStackFrame(stack); + } else { + setExtraStackFrame(null); } } } - } -} -/** - * Given an element, validate that its props follow the propTypes definition, - * provided by the type. - * - * @param {ReactElement} element - */ -function validatePropTypes$1(element) { - { - var type = element.type; + var propTypesMisspellWarningShown$1; + + { + propTypesMisspellWarningShown$1 = false; + } + + function getDeclarationErrorAddendum$1() { + if (ReactCurrentOwner$2.current) { + var name = getComponentNameFromType(ReactCurrentOwner$2.current.type); + + if (name) { + return "\n\nCheck the render method of `" + name + "`."; + } + } - if (type === null || type === undefined || typeof type === "string") { - return; + return ""; } - if (type.$$typeof === REACT_CLIENT_REFERENCE$1) { - return; + function getSourceInfoErrorAddendum$1(source) { + if (source !== undefined) { + var fileName = source.fileName.replace(/^.*[\\\/]/, ""); + var lineNumber = source.lineNumber; + return "\n\nCheck your code at " + fileName + ":" + lineNumber + "."; + } + + return ""; } - var propTypes; + function getSourceInfoErrorAddendumForProps(elementProps) { + if (elementProps !== null && elementProps !== undefined) { + return getSourceInfoErrorAddendum$1(elementProps.__source); + } - if (typeof type === "function") { - propTypes = type.propTypes; - } else if ( - typeof type === "object" && - (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here. - // Inner props are checked in the reconciler. - type.$$typeof === REACT_MEMO_TYPE) - ) { - propTypes = type.propTypes; - } else { - return; + return ""; } + /** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ + + var ownerHasKeyUseWarning$1 = {}; + + function getCurrentComponentErrorInfo$1(parentType) { + var info = getDeclarationErrorAddendum$1(); + + if (!info) { + var parentName = + typeof parentType === "string" + ? parentType + : parentType.displayName || parentType.name; + + if (parentName) { + info = + "\n\nCheck the top-level render call using <" + parentName + ">."; + } + } - if (propTypes) { - // Intentionally inside to avoid triggering lazy initializers: - var name = getComponentNameFromType(type); - checkPropTypes(propTypes, element.props, "prop", name, element); - } else if ( - type.PropTypes !== undefined && - !propTypesMisspellWarningShown$1 - ) { - propTypesMisspellWarningShown$1 = true; // Intentionally inside to avoid triggering lazy initializers: + return info; + } + /** + * Warn if the element doesn't have an explicit key assigned to it. + * This element is in an array. The array could grow and shrink or be + * reordered. All children that haven't already been validated are required to + * have a "key" property assigned to it. Error statuses are cached so a warning + * will only be shown once. + * + * @internal + * @param {ReactElement} element Element that requires a key. + * @param {*} parentType element's parent's type. + */ + + function validateExplicitKey$1(element, parentType) { + if (!element._store || element._store.validated || element.key != null) { + return; + } - var _name = getComponentNameFromType(type); + element._store.validated = true; + var currentComponentErrorInfo = + getCurrentComponentErrorInfo$1(parentType); - error( - "Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?", - _name || "Unknown" - ); - } + if (ownerHasKeyUseWarning$1[currentComponentErrorInfo]) { + return; + } - if ( - typeof type.getDefaultProps === "function" && - !type.getDefaultProps.isReactClassApproved - ) { - error( - "getDefaultProps is only used on classic React.createClass " + - "definitions. Use a static property named `defaultProps` instead." - ); - } - } -} -/** - * Given a fragment, validate that it can only be provided with fragment props - * @param {ReactElement} fragment - */ + ownerHasKeyUseWarning$1[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a + // property, it may be the creator of the child that's responsible for + // assigning it a key. -function validateFragmentProps$1(fragment) { - { - var keys = Object.keys(fragment.props); + var childOwner = ""; - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; + if ( + element && + element._owner && + element._owner !== ReactCurrentOwner$2.current + ) { + // Give the component that originally created this child. + childOwner = + " It was passed a child from " + + getComponentNameFromType(element._owner.type) + + "."; + } - if (key !== "children" && key !== "key") { - setCurrentlyValidatingElement$1(fragment); + { + setCurrentlyValidatingElement$1(element); error( - "Invalid prop `%s` supplied to `React.Fragment`. " + - "React.Fragment can only have `key` and `children` props.", - key + 'Each child in a list should have a unique "key" prop.' + + "%s%s See https://reactjs.org/link/warning-keys for more information.", + currentComponentErrorInfo, + childOwner ); setCurrentlyValidatingElement$1(null); - break; } } + /** + * Ensure that every element either is passed in a static location, in an + * array with an explicit keys property defined, or in an object literal + * with valid key property. + * + * @internal + * @param {ReactNode} node Statically passed child of any type. + * @param {*} parentType node's parent's type. + */ + + function validateChildKeys$1(node, parentType) { + if (typeof node !== "object" || !node) { + return; + } - if (fragment.ref !== null) { - setCurrentlyValidatingElement$1(fragment); - - error("Invalid attribute `ref` supplied to `React.Fragment`."); + if (node.$$typeof === REACT_CLIENT_REFERENCE$1); + else if (isArray(node)) { + for (var i = 0; i < node.length; i++) { + var child = node[i]; - setCurrentlyValidatingElement$1(null); + if (isValidElement$1(child)) { + validateExplicitKey$1(child, parentType); + } + } + } else if (isValidElement$1(node)) { + // This element was passed in a valid location. + if (node._store) { + node._store.validated = true; + } + } else { + var iteratorFn = getIteratorFn(node); + + if (typeof iteratorFn === "function") { + // Entry iterators used to provide implicit keys, + // but now we print a separate warning for them later. + if (iteratorFn !== node.entries) { + var iterator = iteratorFn.call(node); + var step; + + while (!(step = iterator.next()).done) { + if (isValidElement$1(step.value)) { + validateExplicitKey$1(step.value, parentType); + } + } + } + } + } } - } -} -function createElementWithValidation(type, props, children) { - var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to - // succeed and there will likely be errors in render. - - if (!validType) { - var info = ""; + /** + * Given an element, validate that its props follow the propTypes definition, + * provided by the type. + * + * @param {ReactElement} element + */ + + function validatePropTypes$1(element) { + { + var type = element.type; - if ( - type === undefined || - (typeof type === "object" && - type !== null && - Object.keys(type).length === 0) - ) { - 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."; - } + if (type === null || type === undefined || typeof type === "string") { + return; + } - var sourceInfo = getSourceInfoErrorAddendumForProps(props); + if (type.$$typeof === REACT_CLIENT_REFERENCE$1) { + return; + } - if (sourceInfo) { - info += sourceInfo; - } else { - info += getDeclarationErrorAddendum$1(); - } + var propTypes; - var typeString; - - if (type === null) { - typeString = "null"; - } else if (isArray(type)) { - typeString = "array"; - } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) { - typeString = - "<" + (getComponentNameFromType(type.type) || "Unknown") + " />"; - info = - " Did you accidentally export a JSX literal instead of a component?"; - } else { - typeString = typeof type; - } + if (typeof type === "function") { + propTypes = type.propTypes; + } else if ( + typeof type === "object" && + (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here. + // Inner props are checked in the reconciler. + type.$$typeof === REACT_MEMO_TYPE) + ) { + propTypes = type.propTypes; + } else { + return; + } - { - error( - "React.createElement: type is invalid -- expected a string (for " + - "built-in components) or a class/function (for composite " + - "components) but got: %s.%s", - typeString, - info - ); - } - } - - var element = createElement$1.apply(this, arguments); // The result can be nullish if a mock or a custom function is used. - // TODO: Drop this when these are no longer allowed as the type argument. - - if (element == null) { - return element; - } // Skip key warning if the type isn't valid since our key validation logic - // doesn't expect a non-string/function type and can throw confusing errors. - // We don't want exception behavior to differ between dev and prod. - // (Rendering will throw with a helpful message and as soon as the type is - // fixed, the key warnings will appear.) - - if (validType) { - for (var i = 2; i < arguments.length; i++) { - validateChildKeys$1(arguments[i], type); - } - } + if (propTypes) { + // Intentionally inside to avoid triggering lazy initializers: + var name = getComponentNameFromType(type); + checkPropTypes(propTypes, element.props, "prop", name, element); + } else if ( + type.PropTypes !== undefined && + !propTypesMisspellWarningShown$1 + ) { + propTypesMisspellWarningShown$1 = true; // Intentionally inside to avoid triggering lazy initializers: - if (type === REACT_FRAGMENT_TYPE) { - validateFragmentProps$1(element); - } else { - validatePropTypes$1(element); - } + var _name = getComponentNameFromType(type); - return element; -} -var didWarnAboutDeprecatedCreateFactory = false; -function createFactoryWithValidation(type) { - var validatedFactory = createElementWithValidation.bind(null, type); - validatedFactory.type = type; - - { - if (!didWarnAboutDeprecatedCreateFactory) { - didWarnAboutDeprecatedCreateFactory = true; - - warn( - "React.createFactory() is deprecated and will be removed in " + - "a future major release. Consider using JSX " + - "or use React.createElement() directly instead." - ); - } // Legacy hook: remove it - - Object.defineProperty(validatedFactory, "type", { - enumerable: false, - get: function () { - warn( - "Factory.type is deprecated. Access the class directly " + - "before passing it to createFactory." - ); + error( + "Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?", + _name || "Unknown" + ); + } - Object.defineProperty(this, "type", { - value: type - }); - return type; + if ( + typeof type.getDefaultProps === "function" && + !type.getDefaultProps.isReactClassApproved + ) { + error( + "getDefaultProps is only used on classic React.createClass " + + "definitions. Use a static property named `defaultProps` instead." + ); + } } - }); - } + } + /** + * Given a fragment, validate that it can only be provided with fragment props + * @param {ReactElement} fragment + */ - return validatedFactory; -} -function cloneElementWithValidation(element, props, children) { - var newElement = cloneElement$1.apply(this, arguments); + function validateFragmentProps$1(fragment) { + { + var keys = Object.keys(fragment.props); - for (var i = 2; i < arguments.length; i++) { - validateChildKeys$1(arguments[i], newElement.type); - } + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; - validatePropTypes$1(newElement); - return newElement; -} + if (key !== "children" && key !== "key") { + setCurrentlyValidatingElement$1(fragment); + + error( + "Invalid prop `%s` supplied to `React.Fragment`. " + + "React.Fragment can only have `key` and `children` props.", + key + ); -function startTransition(scope, options) { - var prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = {}; - var currentTransition = ReactCurrentBatchConfig.transition; + setCurrentlyValidatingElement$1(null); + break; + } + } - { - ReactCurrentBatchConfig.transition._updatedFibers = new Set(); - } + if (fragment.ref !== null) { + setCurrentlyValidatingElement$1(fragment); - if (enableTransitionTracing) { - if (options !== undefined && options.name !== undefined) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - ReactCurrentBatchConfig.transition.name = options.name; // $FlowFixMe[incompatible-use] found when upgrading Flow + error("Invalid attribute `ref` supplied to `React.Fragment`."); - ReactCurrentBatchConfig.transition.startTime = -1; + setCurrentlyValidatingElement$1(null); + } + } } - } + function createElementWithValidation(type, props, children) { + var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to + // succeed and there will likely be errors in render. - try { - scope(); - } finally { - ReactCurrentBatchConfig.transition = prevTransition; + if (!validType) { + var info = ""; - { - if (prevTransition === null && currentTransition._updatedFibers) { - var updatedFibersCount = currentTransition._updatedFibers.size; + if ( + type === undefined || + (typeof type === "object" && + type !== null && + Object.keys(type).length === 0) + ) { + 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."; + } - currentTransition._updatedFibers.clear(); + var sourceInfo = getSourceInfoErrorAddendumForProps(props); - if (updatedFibersCount > 10) { - 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." + if (sourceInfo) { + info += sourceInfo; + } else { + info += getDeclarationErrorAddendum$1(); + } + + var typeString; + + if (type === null) { + typeString = "null"; + } else if (isArray(type)) { + typeString = "array"; + } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) { + typeString = + "<" + (getComponentNameFromType(type.type) || "Unknown") + " />"; + info = + " Did you accidentally export a JSX literal instead of a component?"; + } else { + typeString = typeof type; + } + + { + error( + "React.createElement: type is invalid -- expected a string (for " + + "built-in components) or a class/function (for composite " + + "components) but got: %s.%s", + typeString, + info ); } } - } - } -} -var didWarnAboutMessageChannel = false; -var enqueueTaskImpl = null; -function enqueueTask(task) { - if (enqueueTaskImpl === null) { - try { - // read require off the module object to get around the bundlers. - // we don't want them to detect a require and bundle a Node polyfill. - var requireString = ("require" + Math.random()).slice(0, 7); - var nodeRequire = module && module[requireString]; // assuming we're in node, let's try to get node's - // version of setImmediate, bypassing fake timers if any. - - enqueueTaskImpl = nodeRequire.call(module, "timers").setImmediate; - } catch (_err) { - // we're in a browser - // we can't use regular timers because they may still be faked - // so we try MessageChannel+postMessage instead - enqueueTaskImpl = function (callback) { - { - if (didWarnAboutMessageChannel === false) { - didWarnAboutMessageChannel = true; + var element = createElement$1.apply(this, arguments); // The result can be nullish if a mock or a custom function is used. + // TODO: Drop this when these are no longer allowed as the type argument. - if (typeof MessageChannel === "undefined") { - error( - "This browser does not have a MessageChannel implementation, " + - "so enqueuing tasks via await act(async () => ...) will fail. " + - "Please file an issue at https://github.com/facebook/react/issues " + - "if you encounter this warning." - ); - } - } + if (element == null) { + return element; + } // Skip key warning if the type isn't valid since our key validation logic + // doesn't expect a non-string/function type and can throw confusing errors. + // We don't want exception behavior to differ between dev and prod. + // (Rendering will throw with a helpful message and as soon as the type is + // fixed, the key warnings will appear.) + + if (validType) { + for (var i = 2; i < arguments.length; i++) { + validateChildKeys$1(arguments[i], type); } + } - var channel = new MessageChannel(); - channel.port1.onmessage = callback; - channel.port2.postMessage(undefined); - }; + if (type === REACT_FRAGMENT_TYPE) { + validateFragmentProps$1(element); + } else { + validatePropTypes$1(element); + } + + return element; } - } + var didWarnAboutDeprecatedCreateFactory = false; + function createFactoryWithValidation(type) { + var validatedFactory = createElementWithValidation.bind(null, type); + validatedFactory.type = type; - return enqueueTaskImpl(task); -} + { + if (!didWarnAboutDeprecatedCreateFactory) { + didWarnAboutDeprecatedCreateFactory = true; -// number of `act` scopes on the stack. + warn( + "React.createFactory() is deprecated and will be removed in " + + "a future major release. Consider using JSX " + + "or use React.createElement() directly instead." + ); + } // Legacy hook: remove it -var actScopeDepth = 0; // We only warn the first time you neglect to await an async `act` scope. + Object.defineProperty(validatedFactory, "type", { + enumerable: false, + get: function () { + warn( + "Factory.type is deprecated. Access the class directly " + + "before passing it to createFactory." + ); -var didWarnNoAwaitAct = false; -function act(callback) { - { - // When ReactCurrentActQueue.current is not null, it signals to React that - // we're currently inside an `act` scope. React will push all its tasks to - // this queue instead of scheduling them with platform APIs. - // - // We set this to an empty array when we first enter an `act` scope, and - // only unset it once we've left the outermost `act` scope — remember that - // `act` calls can be nested. - // - // If we're already inside an `act` scope, reuse the existing queue. - var prevIsBatchingLegacy = ReactCurrentActQueue.isBatchingLegacy; - var prevActQueue = ReactCurrentActQueue.current; - var prevActScopeDepth = actScopeDepth; - actScopeDepth++; - var queue = (ReactCurrentActQueue.current = - prevActQueue !== null ? prevActQueue : []); // Used to reproduce behavior of `batchedUpdates` in legacy mode. Only - // set to `true` while the given callback is executed, not for updates - // triggered during an async event, because this is how the legacy - // implementation of `act` behaved. - - ReactCurrentActQueue.isBatchingLegacy = true; - var result; // This tracks whether the `act` call is awaited. In certain cases, not - // awaiting it is a mistake, so we will detect that and warn. - - var didAwaitActCall = false; - - try { - // Reset this to `false` right before entering the React work loop. The - // only place we ever read this fields is just below, right after running - // the callback. So we don't need to reset after the callback runs. - ReactCurrentActQueue.didScheduleLegacyUpdate = false; - result = callback(); - var didScheduleLegacyUpdate = - ReactCurrentActQueue.didScheduleLegacyUpdate; // Replicate behavior of original `act` implementation in legacy mode, - // which flushed updates immediately after the scope function exits, even - // if it's an async function. - - if (!prevIsBatchingLegacy && didScheduleLegacyUpdate) { - flushActQueue(queue); - } // `isBatchingLegacy` gets reset using the regular stack, not the async - // one used to track `act` scopes. Why, you may be wondering? Because - // that's how it worked before version 18. Yes, it's confusing! We should - // delete legacy mode!! - - ReactCurrentActQueue.isBatchingLegacy = prevIsBatchingLegacy; - } catch (error) { - // `isBatchingLegacy` gets reset using the regular stack, not the async - // one used to track `act` scopes. Why, you may be wondering? Because - // that's how it worked before version 18. Yes, it's confusing! We should - // delete legacy mode!! - ReactCurrentActQueue.isBatchingLegacy = prevIsBatchingLegacy; - popActScope(prevActQueue, prevActScopeDepth); - throw error; + Object.defineProperty(this, "type", { + value: type + }); + return type; + } + }); + } + + return validatedFactory; } + function cloneElementWithValidation(element, props, children) { + var newElement = cloneElement$1.apply(this, arguments); - if ( - result !== null && - typeof result === "object" && // $FlowFixMe[method-unbinding] - typeof result.then === "function" - ) { - // A promise/thenable was returned from the callback. Wait for it to - // resolve before flushing the queue. - // - // If `act` were implemented as an async function, this whole block could - // be a single `await` call. That's really the only difference between - // this branch and the next one. - var thenable = result; // Warn if the an `act` call with an async scope is not awaited. In a - // future release, consider making this an error. + for (var i = 2; i < arguments.length; i++) { + validateChildKeys$1(arguments[i], newElement.type); + } - queueSeveralMicrotasks(function () { - if (!didAwaitActCall && !didWarnNoAwaitAct) { - didWarnNoAwaitAct = true; + validatePropTypes$1(newElement); + return newElement; + } - error( - "You called act(async () => ...) without await. " + - "This could lead to unexpected testing behaviour, " + - "interleaving multiple act calls and mixing their " + - "scopes. " + - "You should - await act(async () => ...);" - ); - } - }); - return { - then: function (resolve, reject) { - didAwaitActCall = true; - thenable.then( - function (returnValue) { - popActScope(prevActQueue, prevActScopeDepth); + function startTransition(scope, options) { + var prevTransition = ReactCurrentBatchConfig.transition; + ReactCurrentBatchConfig.transition = {}; + var currentTransition = ReactCurrentBatchConfig.transition; - if (prevActScopeDepth === 0) { - // We're exiting the outermost `act` scope. Flush the queue. - try { - flushActQueue(queue); - enqueueTask(function () { - return ( - // Recursively flush tasks scheduled by a microtask. - recursivelyFlushAsyncActWork(returnValue, resolve, reject) - ); - }); - } catch (error) { - // `thenable` might not be a real promise, and `flushActQueue` - // might throw, so we need to wrap `flushActQueue` in a - // try/catch. - reject(error); - } - } else { - resolve(returnValue); - } - }, - function (error) { - popActScope(prevActQueue, prevActScopeDepth); - reject(error); - } - ); + { + ReactCurrentBatchConfig.transition._updatedFibers = new Set(); + } + + if (enableTransitionTracing) { + if (options !== undefined && options.name !== undefined) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + ReactCurrentBatchConfig.transition.name = options.name; // $FlowFixMe[incompatible-use] found when upgrading Flow + + ReactCurrentBatchConfig.transition.startTime = -1; } - }; - } else { - var returnValue = result; // The callback is not an async function. Exit the current - // scope immediately. + } - popActScope(prevActQueue, prevActScopeDepth); + try { + scope(); + } finally { + ReactCurrentBatchConfig.transition = prevTransition; - if (prevActScopeDepth === 0) { - // We're exiting the outermost `act` scope. Flush the queue. - flushActQueue(queue); // If the queue is not empty, it implies that we intentionally yielded - // to the main thread, because something suspended. We will continue - // in an asynchronous task. - // - // Warn if something suspends but the `act` call is not awaited. - // In a future release, consider making this an error. + { + if (prevTransition === null && currentTransition._updatedFibers) { + var updatedFibersCount = currentTransition._updatedFibers.size; - if (queue.length !== 0) { - queueSeveralMicrotasks(function () { - if (!didAwaitActCall && !didWarnNoAwaitAct) { - didWarnNoAwaitAct = true; + currentTransition._updatedFibers.clear(); - error( - "A component suspended inside an `act` scope, but the " + - "`act` call was not awaited. When testing React " + - "components that depend on asynchronous data, you must " + - "await the result:\n\n" + - "await act(() => ...)" + if (updatedFibersCount > 10) { + 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." ); } - }); - } // Like many things in this module, this is next part is confusing. - // - // We do not currently require every `act` call that is passed a - // callback to be awaited, through arguably we should. Since this - // callback was synchronous, we need to exit the current scope before - // returning. - // - // However, if thenable we're about to return *is* awaited, we'll - // immediately restore the current scope. So it shouldn't observable. - // - // This doesn't affect the case where the scope callback is async, - // because we always require those calls to be awaited. - // - // TODO: In a future version, consider always requiring all `act` calls - // to be awaited, regardless of whether the callback is sync or async. - - ReactCurrentActQueue.current = null; + } + } } + } - return { - then: function (resolve, reject) { - didAwaitActCall = true; + var didWarnAboutMessageChannel = false; + var enqueueTaskImpl = null; + function enqueueTask(task) { + if (enqueueTaskImpl === null) { + try { + // read require off the module object to get around the bundlers. + // we don't want them to detect a require and bundle a Node polyfill. + var requireString = ("require" + Math.random()).slice(0, 7); + var nodeRequire = module && module[requireString]; // assuming we're in node, let's try to get node's + // version of setImmediate, bypassing fake timers if any. + + enqueueTaskImpl = nodeRequire.call(module, "timers").setImmediate; + } catch (_err) { + // we're in a browser + // we can't use regular timers because they may still be faked + // so we try MessageChannel+postMessage instead + enqueueTaskImpl = function (callback) { + { + if (didWarnAboutMessageChannel === false) { + didWarnAboutMessageChannel = true; + + if (typeof MessageChannel === "undefined") { + error( + "This browser does not have a MessageChannel implementation, " + + "so enqueuing tasks via await act(async () => ...) will fail. " + + "Please file an issue at https://github.com/facebook/react/issues " + + "if you encounter this warning." + ); + } + } + } - if (prevActScopeDepth === 0) { - // If the `act` call is awaited, restore the queue we were - // using before (see long comment above) so we can flush it. - ReactCurrentActQueue.current = queue; - enqueueTask(function () { - return ( - // Recursively flush tasks scheduled by a microtask. - recursivelyFlushAsyncActWork(returnValue, resolve, reject) - ); - }); - } else { - resolve(returnValue); - } + var channel = new MessageChannel(); + channel.port1.onmessage = callback; + channel.port2.postMessage(undefined); + }; } - }; - } - } -} + } -function popActScope(prevActQueue, prevActScopeDepth) { - { - if (prevActScopeDepth !== actScopeDepth - 1) { - error( - "You seem to have overlapping act() calls, this is not supported. " + - "Be sure to await previous act() calls before making a new one. " - ); + return enqueueTaskImpl(task); } - actScopeDepth = prevActScopeDepth; - } -} + // number of `act` scopes on the stack. -function recursivelyFlushAsyncActWork(returnValue, resolve, reject) { - { - // Check if any tasks were scheduled asynchronously. - var queue = ReactCurrentActQueue.current; + var actScopeDepth = 0; // We only warn the first time you neglect to await an async `act` scope. - if (queue !== null) { - if (queue.length !== 0) { - // Async tasks were scheduled, mostly likely in a microtask. - // Keep flushing until there are no more. - try { - flushActQueue(queue); // The work we just performed may have schedule additional async - // tasks. Wait a macrotask and check again. + var didWarnNoAwaitAct = false; + function act(callback) { + { + // When ReactCurrentActQueue.current is not null, it signals to React that + // we're currently inside an `act` scope. React will push all its tasks to + // this queue instead of scheduling them with platform APIs. + // + // We set this to an empty array when we first enter an `act` scope, and + // only unset it once we've left the outermost `act` scope — remember that + // `act` calls can be nested. + // + // If we're already inside an `act` scope, reuse the existing queue. + var prevIsBatchingLegacy = ReactCurrentActQueue.isBatchingLegacy; + var prevActQueue = ReactCurrentActQueue.current; + var prevActScopeDepth = actScopeDepth; + actScopeDepth++; + var queue = (ReactCurrentActQueue.current = + prevActQueue !== null ? prevActQueue : []); // Used to reproduce behavior of `batchedUpdates` in legacy mode. Only + // set to `true` while the given callback is executed, not for updates + // triggered during an async event, because this is how the legacy + // implementation of `act` behaved. + + ReactCurrentActQueue.isBatchingLegacy = true; + var result; // This tracks whether the `act` call is awaited. In certain cases, not + // awaiting it is a mistake, so we will detect that and warn. + + var didAwaitActCall = false; - enqueueTask(function () { - return recursivelyFlushAsyncActWork(returnValue, resolve, reject); - }); + try { + // Reset this to `false` right before entering the React work loop. The + // only place we ever read this fields is just below, right after running + // the callback. So we don't need to reset after the callback runs. + ReactCurrentActQueue.didScheduleLegacyUpdate = false; + result = callback(); + var didScheduleLegacyUpdate = + ReactCurrentActQueue.didScheduleLegacyUpdate; // Replicate behavior of original `act` implementation in legacy mode, + // which flushed updates immediately after the scope function exits, even + // if it's an async function. + + if (!prevIsBatchingLegacy && didScheduleLegacyUpdate) { + flushActQueue(queue); + } // `isBatchingLegacy` gets reset using the regular stack, not the async + // one used to track `act` scopes. Why, you may be wondering? Because + // that's how it worked before version 18. Yes, it's confusing! We should + // delete legacy mode!! + + ReactCurrentActQueue.isBatchingLegacy = prevIsBatchingLegacy; } catch (error) { - // Leave remaining tasks on the queue if something throws. - reject(error); + // `isBatchingLegacy` gets reset using the regular stack, not the async + // one used to track `act` scopes. Why, you may be wondering? Because + // that's how it worked before version 18. Yes, it's confusing! We should + // delete legacy mode!! + ReactCurrentActQueue.isBatchingLegacy = prevIsBatchingLegacy; + popActScope(prevActQueue, prevActScopeDepth); + throw error; } - } else { - // The queue is empty. We can finish. - ReactCurrentActQueue.current = null; - resolve(returnValue); - } - } else { - resolve(returnValue); - } - } -} - -var isFlushing = false; -function flushActQueue(queue) { - { - if (!isFlushing) { - // Prevent re-entrance. - isFlushing = true; - var i = 0; + if ( + result !== null && + typeof result === "object" && // $FlowFixMe[method-unbinding] + typeof result.then === "function" + ) { + // A promise/thenable was returned from the callback. Wait for it to + // resolve before flushing the queue. + // + // If `act` were implemented as an async function, this whole block could + // be a single `await` call. That's really the only difference between + // this branch and the next one. + var thenable = result; // Warn if the an `act` call with an async scope is not awaited. In a + // future release, consider making this an error. - try { - for (; i < queue.length; i++) { - var callback = queue[i]; - - do { - ReactCurrentActQueue.didUsePromise = false; - var continuation = callback(false); - - if (continuation !== null) { - if (ReactCurrentActQueue.didUsePromise) { - // The component just suspended. Yield to the main thread in - // case the promise is already resolved. If so, it will ping in - // a microtask and we can resume without unwinding the stack. - queue[i] = callback; - queue.splice(0, i); - return; - } + queueSeveralMicrotasks(function () { + if (!didAwaitActCall && !didWarnNoAwaitAct) { + didWarnNoAwaitAct = true; - callback = continuation; - } else { - break; + error( + "You called act(async () => ...) without await. " + + "This could lead to unexpected testing behaviour, " + + "interleaving multiple act calls and mixing their " + + "scopes. " + + "You should - await act(async () => ...);" + ); } - } while (true); - } // We flushed the entire queue. - - queue.length = 0; - } catch (error) { - // If something throws, leave the remaining callbacks on the queue. - queue.splice(0, i + 1); - throw error; - } finally { - isFlushing = false; - } - } - } -} // Some of our warnings attempt to detect if the `act` call is awaited by -// checking in an asynchronous task. Wait a few microtasks before checking. The -// only reason one isn't sufficient is we want to accommodate the case where an -// `act` call is returned from an async function without first being awaited, -// since that's a somewhat common pattern. If you do this too many times in a -// nested sequence, you might get a warning, but you can always fix by awaiting -// the call. -// -// A macrotask would also work (and is the fallback) but depending on the test -// environment it may cause the warning to fire too late. - -var queueSeveralMicrotasks = - typeof queueMicrotask === "function" - ? function (callback) { - queueMicrotask(function () { - return queueMicrotask(callback); - }); - } - : enqueueTask; - -var createElement = createElementWithValidation; -var cloneElement = cloneElementWithValidation; -var createFactory = createFactoryWithValidation; -var Children = { - map: mapChildren, - forEach: forEachChildren, - count: countChildren, - toArray: toArray, - only: onlyChild -}; - -var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; -var RESERVED_PROPS = { - key: true, - ref: true, - __self: true, - __source: true -}; -var specialPropKeyWarningShown; -var specialPropRefWarningShown; -var didWarnAboutStringRefs; - -{ - didWarnAboutStringRefs = {}; -} - -function hasValidRef(config) { - { - if (hasOwnProperty.call(config, "ref")) { - var getter = Object.getOwnPropertyDescriptor(config, "ref").get; + }); + return { + then: function (resolve, reject) { + didAwaitActCall = true; + thenable.then( + function (returnValue) { + popActScope(prevActQueue, prevActScopeDepth); + + if (prevActScopeDepth === 0) { + // We're exiting the outermost `act` scope. Flush the queue. + try { + flushActQueue(queue); + enqueueTask(function () { + return ( + // Recursively flush tasks scheduled by a microtask. + recursivelyFlushAsyncActWork( + returnValue, + resolve, + reject + ) + ); + }); + } catch (error) { + // `thenable` might not be a real promise, and `flushActQueue` + // might throw, so we need to wrap `flushActQueue` in a + // try/catch. + reject(error); + } + } else { + resolve(returnValue); + } + }, + function (error) { + popActScope(prevActQueue, prevActScopeDepth); + reject(error); + } + ); + } + }; + } else { + var returnValue = result; // The callback is not an async function. Exit the current + // scope immediately. - if (getter && getter.isReactWarning) { - return false; - } - } - } + popActScope(prevActQueue, prevActScopeDepth); - return config.ref !== undefined; -} + if (prevActScopeDepth === 0) { + // We're exiting the outermost `act` scope. Flush the queue. + flushActQueue(queue); // If the queue is not empty, it implies that we intentionally yielded + // to the main thread, because something suspended. We will continue + // in an asynchronous task. + // + // Warn if something suspends but the `act` call is not awaited. + // In a future release, consider making this an error. + + if (queue.length !== 0) { + queueSeveralMicrotasks(function () { + if (!didAwaitActCall && !didWarnNoAwaitAct) { + didWarnNoAwaitAct = true; + + error( + "A component suspended inside an `act` scope, but the " + + "`act` call was not awaited. When testing React " + + "components that depend on asynchronous data, you must " + + "await the result:\n\n" + + "await act(() => ...)" + ); + } + }); + } // Like many things in this module, this is next part is confusing. + // + // We do not currently require every `act` call that is passed a + // callback to be awaited, through arguably we should. Since this + // callback was synchronous, we need to exit the current scope before + // returning. + // + // However, if thenable we're about to return *is* awaited, we'll + // immediately restore the current scope. So it shouldn't observable. + // + // This doesn't affect the case where the scope callback is async, + // because we always require those calls to be awaited. + // + // TODO: In a future version, consider always requiring all `act` calls + // to be awaited, regardless of whether the callback is sync or async. + + ReactCurrentActQueue.current = null; + } -function hasValidKey(config) { - { - if (hasOwnProperty.call(config, "key")) { - var getter = Object.getOwnPropertyDescriptor(config, "key").get; + return { + then: function (resolve, reject) { + didAwaitActCall = true; - if (getter && getter.isReactWarning) { - return false; + if (prevActScopeDepth === 0) { + // If the `act` call is awaited, restore the queue we were + // using before (see long comment above) so we can flush it. + ReactCurrentActQueue.current = queue; + enqueueTask(function () { + return ( + // Recursively flush tasks scheduled by a microtask. + recursivelyFlushAsyncActWork(returnValue, resolve, reject) + ); + }); + } else { + resolve(returnValue); + } + } + }; + } } } - } - - return config.key !== undefined; -} - -function warnIfStringRefCannotBeAutoConverted(config, self) { - { - if ( - typeof config.ref === "string" && - ReactCurrentOwner$1.current && - self && - ReactCurrentOwner$1.current.stateNode !== self - ) { - var componentName = getComponentNameFromType( - ReactCurrentOwner$1.current.type - ); - if (!didWarnAboutStringRefs[componentName]) { - error( - 'Component "%s" contains the string ref "%s". ' + - "Support for string refs will be removed in a future major release. " + - "This case cannot be automatically converted to an arrow function. " + - "We ask you to manually fix this case by using useRef() or createRef() instead. " + - "Learn more about using refs safely here: " + - "https://reactjs.org/link/strict-mode-string-ref", - getComponentNameFromType(ReactCurrentOwner$1.current.type), - config.ref - ); + function popActScope(prevActQueue, prevActScopeDepth) { + { + if (prevActScopeDepth !== actScopeDepth - 1) { + error( + "You seem to have overlapping act() calls, this is not supported. " + + "Be sure to await previous act() calls before making a new one. " + ); + } - didWarnAboutStringRefs[componentName] = true; + actScopeDepth = prevActScopeDepth; } } - } -} -function defineKeyPropWarningGetter(props, displayName) { - { - var warnAboutAccessingKey = function () { - if (!specialPropKeyWarningShown) { - specialPropKeyWarningShown = true; - - error( - "%s: `key` is not a prop. Trying to access it will result " + - "in `undefined` being returned. If you need to access the same " + - "value within the child component, you should pass it as a different " + - "prop. (https://reactjs.org/link/special-props)", - displayName - ); + function recursivelyFlushAsyncActWork(returnValue, resolve, reject) { + { + // Check if any tasks were scheduled asynchronously. + var queue = ReactCurrentActQueue.current; + + if (queue !== null) { + if (queue.length !== 0) { + // Async tasks were scheduled, mostly likely in a microtask. + // Keep flushing until there are no more. + try { + flushActQueue(queue); // The work we just performed may have schedule additional async + // tasks. Wait a macrotask and check again. + + enqueueTask(function () { + return recursivelyFlushAsyncActWork( + returnValue, + resolve, + reject + ); + }); + } catch (error) { + // Leave remaining tasks on the queue if something throws. + reject(error); + } + } else { + // The queue is empty. We can finish. + ReactCurrentActQueue.current = null; + resolve(returnValue); + } + } else { + resolve(returnValue); + } } - }; + } - warnAboutAccessingKey.isReactWarning = true; - Object.defineProperty(props, "key", { - get: warnAboutAccessingKey, - configurable: true - }); - } -} + var isFlushing = false; -function defineRefPropWarningGetter(props, displayName) { - { - var warnAboutAccessingRef = function () { - if (!specialPropRefWarningShown) { - specialPropRefWarningShown = true; + function flushActQueue(queue) { + { + if (!isFlushing) { + // Prevent re-entrance. + isFlushing = true; + var i = 0; + + try { + for (; i < queue.length; i++) { + var callback = queue[i]; + + do { + ReactCurrentActQueue.didUsePromise = false; + var continuation = callback(false); + + if (continuation !== null) { + if (ReactCurrentActQueue.didUsePromise) { + // The component just suspended. Yield to the main thread in + // case the promise is already resolved. If so, it will ping in + // a microtask and we can resume without unwinding the stack. + queue[i] = callback; + queue.splice(0, i); + return; + } - error( - "%s: `ref` is not a prop. Trying to access it will result " + - "in `undefined` being returned. If you need to access the same " + - "value within the child component, you should pass it as a different " + - "prop. (https://reactjs.org/link/special-props)", - displayName - ); + callback = continuation; + } else { + break; + } + } while (true); + } // We flushed the entire queue. + + queue.length = 0; + } catch (error) { + // If something throws, leave the remaining callbacks on the queue. + queue.splice(0, i + 1); + throw error; + } finally { + isFlushing = false; + } + } } + } // Some of our warnings attempt to detect if the `act` call is awaited by + // checking in an asynchronous task. Wait a few microtasks before checking. The + // only reason one isn't sufficient is we want to accommodate the case where an + // `act` call is returned from an async function without first being awaited, + // since that's a somewhat common pattern. If you do this too many times in a + // nested sequence, you might get a warning, but you can always fix by awaiting + // the call. + // + // A macrotask would also work (and is the fallback) but depending on the test + // environment it may cause the warning to fire too late. + + var queueSeveralMicrotasks = + typeof queueMicrotask === "function" + ? function (callback) { + queueMicrotask(function () { + return queueMicrotask(callback); + }); + } + : enqueueTask; + + var createElement = createElementWithValidation; + var cloneElement = cloneElementWithValidation; + var createFactory = createFactoryWithValidation; + var Children = { + map: mapChildren, + forEach: forEachChildren, + count: countChildren, + toArray: toArray, + only: onlyChild }; - warnAboutAccessingRef.isReactWarning = true; - Object.defineProperty(props, "ref", { - get: warnAboutAccessingRef, - configurable: true - }); - } -} -/** - * Factory method to create a new React element. This no longer adheres to - * the class pattern, so do not use new to call it. Also, instanceof check - * will not work. Instead test $$typeof field against Symbol.for('react.element') to check - * if something is a React Element. - * - * @param {*} type - * @param {*} props - * @param {*} key - * @param {string|object} ref - * @param {*} owner - * @param {*} self A *temporary* helper to detect places where `this` is - * different from the `owner` when React.createElement is called, so that we - * can warn. We want to get rid of owner and replace string `ref`s with arrow - * functions, and as long as `this` and owner are the same, there will be no - * change in behavior. - * @param {*} source An annotation object (added by a transpiler or otherwise) - * indicating filename, line number, and/or other information. - * @internal - */ + var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; + var RESERVED_PROPS = { + key: true, + ref: true, + __self: true, + __source: true + }; + var specialPropKeyWarningShown; + var specialPropRefWarningShown; + var didWarnAboutStringRefs; -function ReactElement(type, key, ref, self, source, owner, props) { - var element = { - // This tag allows us to uniquely identify this as a React Element - $$typeof: REACT_ELEMENT_TYPE, - // Built-in properties that belong on the element - type: type, - key: key, - ref: ref, - props: props, - // Record the component responsible for creating this element. - _owner: owner - }; - - { - // The validation flag is currently mutative. We put it on - // an external backing store so that we can freeze the whole object. - // This can be replaced with a WeakMap once they are implemented in - // commonly used development environments. - element._store = {}; // To make comparing ReactElements easier for testing purposes, we make - // the validation flag non-enumerable (where possible, which should - // include every environment we run tests in), so the test framework - // ignores it. - - Object.defineProperty(element._store, "validated", { - configurable: false, - enumerable: false, - writable: true, - value: false - }); // self and source are DEV only properties. - - Object.defineProperty(element, "_self", { - configurable: false, - enumerable: false, - writable: false, - value: self - }); // Two elements created in two different places should be considered - // equal for testing purposes and therefore we hide it from enumeration. - - Object.defineProperty(element, "_source", { - configurable: false, - enumerable: false, - writable: false, - value: source - }); - - if (Object.freeze) { - Object.freeze(element.props); - Object.freeze(element); + { + didWarnAboutStringRefs = {}; } - } - return element; -} -/** - * https://github.com/reactjs/rfcs/pull/107 - * @param {*} type - * @param {object} props - * @param {string} key - */ + function hasValidRef(config) { + { + if (hasOwnProperty.call(config, "ref")) { + var getter = Object.getOwnPropertyDescriptor(config, "ref").get; -function jsxDEV$1(type, config, maybeKey, source, self) { - { - var propName; // Reserved names are extracted + if (getter && getter.isReactWarning) { + return false; + } + } + } - var props = {}; - var key = null; - var ref = null; // Currently, key can be spread in as a prop. This causes a potential - // issue if key is also explicitly declared (ie.
- // or
). We want to deprecate key spread, - // but as an intermediary step, we will use jsxDEV for everything except - //
, because we aren't currently able to tell if - // key is explicitly declared to be undefined or not. + return config.ref !== undefined; + } - if (maybeKey !== undefined) { + function hasValidKey(config) { { - checkKeyStringCoercion(maybeKey); + if (hasOwnProperty.call(config, "key")) { + var getter = Object.getOwnPropertyDescriptor(config, "key").get; + + if (getter && getter.isReactWarning) { + return false; + } + } } - key = "" + maybeKey; + return config.key !== undefined; } - if (hasValidKey(config)) { + function warnIfStringRefCannotBeAutoConverted(config, self) { { - checkKeyStringCoercion(config.key); - } + if ( + typeof config.ref === "string" && + ReactCurrentOwner$1.current && + self && + ReactCurrentOwner$1.current.stateNode !== self + ) { + var componentName = getComponentNameFromType( + ReactCurrentOwner$1.current.type + ); + + if (!didWarnAboutStringRefs[componentName]) { + error( + 'Component "%s" contains the string ref "%s". ' + + "Support for string refs will be removed in a future major release. " + + "This case cannot be automatically converted to an arrow function. " + + "We ask you to manually fix this case by using useRef() or createRef() instead. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-string-ref", + getComponentNameFromType(ReactCurrentOwner$1.current.type), + config.ref + ); - key = "" + config.key; + didWarnAboutStringRefs[componentName] = true; + } + } + } } - if (hasValidRef(config)) { - ref = config.ref; - warnIfStringRefCannotBeAutoConverted(config, self); - } // Remaining properties are added to a new props object + function defineKeyPropWarningGetter(props, displayName) { + { + var warnAboutAccessingKey = function () { + if (!specialPropKeyWarningShown) { + specialPropKeyWarningShown = true; - for (propName in config) { - if ( - hasOwnProperty.call(config, propName) && - !RESERVED_PROPS.hasOwnProperty(propName) - ) { - props[propName] = config[propName]; + error( + "%s: `key` is not a prop. Trying to access it will result " + + "in `undefined` being returned. If you need to access the same " + + "value within the child component, you should pass it as a different " + + "prop. (https://reactjs.org/link/special-props)", + displayName + ); + } + }; + + warnAboutAccessingKey.isReactWarning = true; + Object.defineProperty(props, "key", { + get: warnAboutAccessingKey, + configurable: true + }); } - } // Resolve default props + } + + function defineRefPropWarningGetter(props, displayName) { + { + var warnAboutAccessingRef = function () { + if (!specialPropRefWarningShown) { + specialPropRefWarningShown = true; - if (type && type.defaultProps) { - var defaultProps = type.defaultProps; + error( + "%s: `ref` is not a prop. Trying to access it will result " + + "in `undefined` being returned. If you need to access the same " + + "value within the child component, you should pass it as a different " + + "prop. (https://reactjs.org/link/special-props)", + displayName + ); + } + }; - for (propName in defaultProps) { - if (props[propName] === undefined) { - props[propName] = defaultProps[propName]; - } + warnAboutAccessingRef.isReactWarning = true; + Object.defineProperty(props, "ref", { + get: warnAboutAccessingRef, + configurable: true + }); } } + /** + * Factory method to create a new React element. This no longer adheres to + * the class pattern, so do not use new to call it. Also, instanceof check + * will not work. Instead test $$typeof field against Symbol.for('react.element') to check + * if something is a React Element. + * + * @param {*} type + * @param {*} props + * @param {*} key + * @param {string|object} ref + * @param {*} owner + * @param {*} self A *temporary* helper to detect places where `this` is + * different from the `owner` when React.createElement is called, so that we + * can warn. We want to get rid of owner and replace string `ref`s with arrow + * functions, and as long as `this` and owner are the same, there will be no + * change in behavior. + * @param {*} source An annotation object (added by a transpiler or otherwise) + * indicating filename, line number, and/or other information. + * @internal + */ + + function ReactElement(type, key, ref, self, source, owner, props) { + var element = { + // This tag allows us to uniquely identify this as a React Element + $$typeof: REACT_ELEMENT_TYPE, + // Built-in properties that belong on the element + type: type, + key: key, + ref: ref, + props: props, + // Record the component responsible for creating this element. + _owner: owner + }; - if (key || ref) { - var displayName = - typeof type === "function" - ? type.displayName || type.name || "Unknown" - : type; + { + // The validation flag is currently mutative. We put it on + // an external backing store so that we can freeze the whole object. + // This can be replaced with a WeakMap once they are implemented in + // commonly used development environments. + element._store = {}; // To make comparing ReactElements easier for testing purposes, we make + // the validation flag non-enumerable (where possible, which should + // include every environment we run tests in), so the test framework + // ignores it. + + Object.defineProperty(element._store, "validated", { + configurable: false, + enumerable: false, + writable: true, + value: false + }); // self and source are DEV only properties. + + Object.defineProperty(element, "_self", { + configurable: false, + enumerable: false, + writable: false, + value: self + }); // Two elements created in two different places should be considered + // equal for testing purposes and therefore we hide it from enumeration. + + Object.defineProperty(element, "_source", { + configurable: false, + enumerable: false, + writable: false, + value: source + }); - if (key) { - defineKeyPropWarningGetter(props, displayName); + if (Object.freeze) { + Object.freeze(element.props); + Object.freeze(element); + } } - if (ref) { - defineRefPropWarningGetter(props, displayName); - } + return element; } + /** + * https://github.com/reactjs/rfcs/pull/107 + * @param {*} type + * @param {object} props + * @param {string} key + */ + + function jsxDEV$1(type, config, maybeKey, source, self) { + { + var propName; // Reserved names are extracted + + var props = {}; + var key = null; + var ref = null; // Currently, key can be spread in as a prop. This causes a potential + // issue if key is also explicitly declared (ie.
+ // or
). We want to deprecate key spread, + // but as an intermediary step, we will use jsxDEV for everything except + //
, because we aren't currently able to tell if + // key is explicitly declared to be undefined or not. + + if (maybeKey !== undefined) { + { + checkKeyStringCoercion(maybeKey); + } - return ReactElement( - type, - key, - ref, - self, - source, - ReactCurrentOwner$1.current, - props - ); - } -} + key = "" + maybeKey; + } -var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; -var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; -var REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"); + if (hasValidKey(config)) { + { + checkKeyStringCoercion(config.key); + } -function setCurrentlyValidatingElement(element) { - { - if (element) { - var owner = element._owner; - var stack = describeUnknownElementTypeFrameInDEV( - element.type, - element._source, - owner ? owner.type : null - ); - ReactDebugCurrentFrame.setExtraStackFrame(stack); - } else { - ReactDebugCurrentFrame.setExtraStackFrame(null); - } - } -} + key = "" + config.key; + } -var propTypesMisspellWarningShown; + if (hasValidRef(config)) { + ref = config.ref; + warnIfStringRefCannotBeAutoConverted(config, self); + } // Remaining properties are added to a new props object + + for (propName in config) { + if ( + hasOwnProperty.call(config, propName) && + !RESERVED_PROPS.hasOwnProperty(propName) + ) { + props[propName] = config[propName]; + } + } // Resolve default props -{ - propTypesMisspellWarningShown = false; -} -/** - * Verifies the object is a ReactElement. - * See https://reactjs.org/docs/react-api.html#isvalidelement - * @param {?object} object - * @return {boolean} True if `object` is a ReactElement. - * @final - */ + if (type && type.defaultProps) { + var defaultProps = type.defaultProps; -function isValidElement(object) { - { - return ( - typeof object === "object" && - object !== null && - object.$$typeof === REACT_ELEMENT_TYPE - ); - } -} + for (propName in defaultProps) { + if (props[propName] === undefined) { + props[propName] = defaultProps[propName]; + } + } + } + + if (key || ref) { + var displayName = + typeof type === "function" + ? type.displayName || type.name || "Unknown" + : type; + + if (key) { + defineKeyPropWarningGetter(props, displayName); + } -function getDeclarationErrorAddendum() { - { - if (ReactCurrentOwner.current) { - var name = getComponentNameFromType(ReactCurrentOwner.current.type); + if (ref) { + defineRefPropWarningGetter(props, displayName); + } + } - if (name) { - return "\n\nCheck the render method of `" + name + "`."; + return ReactElement( + type, + key, + ref, + self, + source, + ReactCurrentOwner$1.current, + props + ); } } - return ""; - } -} + var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + var REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"); -function getSourceInfoErrorAddendum(source) { - { - if (source !== undefined) { - var fileName = source.fileName.replace(/^.*[\\\/]/, ""); - var lineNumber = source.lineNumber; - return "\n\nCheck your code at " + fileName + ":" + lineNumber + "."; + function setCurrentlyValidatingElement(element) { + { + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV( + element.type, + element._source, + owner ? owner.type : null + ); + ReactDebugCurrentFrame.setExtraStackFrame(stack); + } else { + ReactDebugCurrentFrame.setExtraStackFrame(null); + } + } } - return ""; - } -} -/** - * Warn if there's no key explicitly set on dynamic arrays of children or - * object keys are not valid. This allows us to keep track of children between - * updates. - */ + var propTypesMisspellWarningShown; -var ownerHasKeyUseWarning = {}; + { + propTypesMisspellWarningShown = false; + } + /** + * Verifies the object is a ReactElement. + * See https://reactjs.org/docs/react-api.html#isvalidelement + * @param {?object} object + * @return {boolean} True if `object` is a ReactElement. + * @final + */ + + function isValidElement(object) { + { + return ( + typeof object === "object" && + object !== null && + object.$$typeof === REACT_ELEMENT_TYPE + ); + } + } -function getCurrentComponentErrorInfo(parentType) { - { - var info = getDeclarationErrorAddendum(); + function getDeclarationErrorAddendum() { + { + if (ReactCurrentOwner.current) { + var name = getComponentNameFromType(ReactCurrentOwner.current.type); - if (!info) { - var parentName = - typeof parentType === "string" - ? parentType - : parentType.displayName || parentType.name; + if (name) { + return "\n\nCheck the render method of `" + name + "`."; + } + } - if (parentName) { - info = - "\n\nCheck the top-level render call using <" + parentName + ">."; + return ""; } } - return info; - } -} -/** - * Warn if the element doesn't have an explicit key assigned to it. - * This element is in an array. The array could grow and shrink or be - * reordered. All children that haven't already been validated are required to - * have a "key" property assigned to it. Error statuses are cached so a warning - * will only be shown once. - * - * @internal - * @param {ReactElement} element Element that requires a key. - * @param {*} parentType element's parent's type. - */ + function getSourceInfoErrorAddendum(source) { + { + if (source !== undefined) { + var fileName = source.fileName.replace(/^.*[\\\/]/, ""); + var lineNumber = source.lineNumber; + return "\n\nCheck your code at " + fileName + ":" + lineNumber + "."; + } -function validateExplicitKey(element, parentType) { - { - if (!element._store || element._store.validated || element.key != null) { - return; + return ""; + } } + /** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ - element._store.validated = true; - var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType); + var ownerHasKeyUseWarning = {}; - if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { - return; - } + function getCurrentComponentErrorInfo(parentType) { + { + var info = getDeclarationErrorAddendum(); - ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a - // property, it may be the creator of the child that's responsible for - // assigning it a key. + if (!info) { + var parentName = + typeof parentType === "string" + ? parentType + : parentType.displayName || parentType.name; - var childOwner = ""; + if (parentName) { + info = + "\n\nCheck the top-level render call using <" + parentName + ">."; + } + } - if ( - element && - element._owner && - element._owner !== ReactCurrentOwner.current - ) { - // Give the component that originally created this child. - childOwner = - " It was passed a child from " + - getComponentNameFromType(element._owner.type) + - "."; + return info; + } } + /** + * Warn if the element doesn't have an explicit key assigned to it. + * This element is in an array. The array could grow and shrink or be + * reordered. All children that haven't already been validated are required to + * have a "key" property assigned to it. Error statuses are cached so a warning + * will only be shown once. + * + * @internal + * @param {ReactElement} element Element that requires a key. + * @param {*} parentType element's parent's type. + */ + + function validateExplicitKey(element, parentType) { + { + if ( + !element._store || + element._store.validated || + element.key != null + ) { + return; + } - setCurrentlyValidatingElement(element); - - error( - 'Each child in a list should have a unique "key" prop.' + - "%s%s See https://reactjs.org/link/warning-keys for more information.", - currentComponentErrorInfo, - childOwner - ); + element._store.validated = true; + var currentComponentErrorInfo = + getCurrentComponentErrorInfo(parentType); - setCurrentlyValidatingElement(null); - } -} -/** - * Ensure that every element either is passed in a static location, in an - * array with an explicit keys property defined, or in an object literal - * with valid key property. - * - * @internal - * @param {ReactNode} node Statically passed child of any type. - * @param {*} parentType node's parent's type. - */ + if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { + return; + } -function validateChildKeys(node, parentType) { - { - if (typeof node !== "object" || !node) { - return; - } + ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a + // property, it may be the creator of the child that's responsible for + // assigning it a key. - if (node.$$typeof === REACT_CLIENT_REFERENCE); - else if (isArray(node)) { - for (var i = 0; i < node.length; i++) { - var child = node[i]; + var childOwner = ""; - if (isValidElement(child)) { - validateExplicitKey(child, parentType); + if ( + element && + element._owner && + element._owner !== ReactCurrentOwner.current + ) { + // Give the component that originally created this child. + childOwner = + " It was passed a child from " + + getComponentNameFromType(element._owner.type) + + "."; } + + setCurrentlyValidatingElement(element); + + error( + 'Each child in a list should have a unique "key" prop.' + + "%s%s See https://reactjs.org/link/warning-keys for more information.", + currentComponentErrorInfo, + childOwner + ); + + setCurrentlyValidatingElement(null); } - } else if (isValidElement(node)) { - // This element was passed in a valid location. - if (node._store) { - node._store.validated = true; - } - } else { - var iteratorFn = getIteratorFn(node); - - if (typeof iteratorFn === "function") { - // Entry iterators used to provide implicit keys, - // but now we print a separate warning for them later. - if (iteratorFn !== node.entries) { - var iterator = iteratorFn.call(node); - var step; + } + /** + * Ensure that every element either is passed in a static location, in an + * array with an explicit keys property defined, or in an object literal + * with valid key property. + * + * @internal + * @param {ReactNode} node Statically passed child of any type. + * @param {*} parentType node's parent's type. + */ + + function validateChildKeys(node, parentType) { + { + if (typeof node !== "object" || !node) { + return; + } - while (!(step = iterator.next()).done) { - if (isValidElement(step.value)) { - validateExplicitKey(step.value, parentType); + if (node.$$typeof === REACT_CLIENT_REFERENCE); + else if (isArray(node)) { + for (var i = 0; i < node.length; i++) { + var child = node[i]; + + if (isValidElement(child)) { + validateExplicitKey(child, parentType); + } + } + } else if (isValidElement(node)) { + // This element was passed in a valid location. + if (node._store) { + node._store.validated = true; + } + } else { + var iteratorFn = getIteratorFn(node); + + if (typeof iteratorFn === "function") { + // Entry iterators used to provide implicit keys, + // but now we print a separate warning for them later. + if (iteratorFn !== node.entries) { + var iterator = iteratorFn.call(node); + var step; + + while (!(step = iterator.next()).done) { + if (isValidElement(step.value)) { + validateExplicitKey(step.value, parentType); + } + } } } } } } - } -} -/** - * Given an element, validate that its props follow the propTypes definition, - * provided by the type. - * - * @param {ReactElement} element - */ - -function validatePropTypes(element) { - { - var type = element.type; + /** + * Given an element, validate that its props follow the propTypes definition, + * provided by the type. + * + * @param {ReactElement} element + */ + + function validatePropTypes(element) { + { + var type = element.type; - if (type === null || type === undefined || typeof type === "string") { - return; - } + if (type === null || type === undefined || typeof type === "string") { + return; + } - if (type.$$typeof === REACT_CLIENT_REFERENCE) { - return; - } + if (type.$$typeof === REACT_CLIENT_REFERENCE) { + return; + } - var propTypes; + var propTypes; - if (typeof type === "function") { - propTypes = type.propTypes; - } else if ( - typeof type === "object" && - (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here. - // Inner props are checked in the reconciler. - type.$$typeof === REACT_MEMO_TYPE) - ) { - propTypes = type.propTypes; - } else { - return; - } + if (typeof type === "function") { + propTypes = type.propTypes; + } else if ( + typeof type === "object" && + (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here. + // Inner props are checked in the reconciler. + type.$$typeof === REACT_MEMO_TYPE) + ) { + propTypes = type.propTypes; + } else { + return; + } - if (propTypes) { - // Intentionally inside to avoid triggering lazy initializers: - var name = getComponentNameFromType(type); - checkPropTypes(propTypes, element.props, "prop", name, element); - } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) { - propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers: + if (propTypes) { + // Intentionally inside to avoid triggering lazy initializers: + var name = getComponentNameFromType(type); + checkPropTypes(propTypes, element.props, "prop", name, element); + } else if ( + type.PropTypes !== undefined && + !propTypesMisspellWarningShown + ) { + propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers: - var _name = getComponentNameFromType(type); + var _name = getComponentNameFromType(type); - error( - "Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?", - _name || "Unknown" - ); - } + error( + "Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?", + _name || "Unknown" + ); + } - if ( - typeof type.getDefaultProps === "function" && - !type.getDefaultProps.isReactClassApproved - ) { - error( - "getDefaultProps is only used on classic React.createClass " + - "definitions. Use a static property named `defaultProps` instead." - ); + if ( + typeof type.getDefaultProps === "function" && + !type.getDefaultProps.isReactClassApproved + ) { + error( + "getDefaultProps is only used on classic React.createClass " + + "definitions. Use a static property named `defaultProps` instead." + ); + } + } } - } -} -/** - * Given a fragment, validate that it can only be provided with fragment props - * @param {ReactElement} fragment - */ + /** + * Given a fragment, validate that it can only be provided with fragment props + * @param {ReactElement} fragment + */ -function validateFragmentProps(fragment) { - { - var keys = Object.keys(fragment.props); + function validateFragmentProps(fragment) { + { + var keys = Object.keys(fragment.props); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; - if (key !== "children" && key !== "key") { - setCurrentlyValidatingElement(fragment); + if (key !== "children" && key !== "key") { + setCurrentlyValidatingElement(fragment); - error( - "Invalid prop `%s` supplied to `React.Fragment`. " + - "React.Fragment can only have `key` and `children` props.", - key - ); + error( + "Invalid prop `%s` supplied to `React.Fragment`. " + + "React.Fragment can only have `key` and `children` props.", + key + ); - setCurrentlyValidatingElement(null); - break; - } - } + setCurrentlyValidatingElement(null); + break; + } + } - if (fragment.ref !== null) { - setCurrentlyValidatingElement(fragment); + if (fragment.ref !== null) { + setCurrentlyValidatingElement(fragment); - error("Invalid attribute `ref` supplied to `React.Fragment`."); + error("Invalid attribute `ref` supplied to `React.Fragment`."); - setCurrentlyValidatingElement(null); + setCurrentlyValidatingElement(null); + } + } } - } -} -var didWarnAboutKeySpread = {}; -function jsxWithValidation(type, props, key, isStaticChildren, source, self) { - { - var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to - // succeed and there will likely be errors in render. + var didWarnAboutKeySpread = {}; + function jsxWithValidation( + type, + props, + key, + isStaticChildren, + source, + self + ) { + { + var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to + // succeed and there will likely be errors in render. + + if (!validType) { + var info = ""; + + if ( + type === undefined || + (typeof type === "object" && + type !== null && + Object.keys(type).length === 0) + ) { + 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."; + } - if (!validType) { - var info = ""; + var sourceInfo = getSourceInfoErrorAddendum(source); - if ( - type === undefined || - (typeof type === "object" && - type !== null && - Object.keys(type).length === 0) - ) { - 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."; - } + if (sourceInfo) { + info += sourceInfo; + } else { + info += getDeclarationErrorAddendum(); + } - var sourceInfo = getSourceInfoErrorAddendum(source); + var typeString; + + if (type === null) { + typeString = "null"; + } else if (isArray(type)) { + typeString = "array"; + } else if ( + type !== undefined && + type.$$typeof === REACT_ELEMENT_TYPE + ) { + typeString = + "<" + (getComponentNameFromType(type.type) || "Unknown") + " />"; + info = + " Did you accidentally export a JSX literal instead of a component?"; + } else { + typeString = typeof type; + } - if (sourceInfo) { - info += sourceInfo; - } else { - info += getDeclarationErrorAddendum(); - } + error( + "React.jsx: type is invalid -- expected a string (for " + + "built-in components) or a class/function (for composite " + + "components) but got: %s.%s", + typeString, + info + ); + } - var typeString; - - if (type === null) { - typeString = "null"; - } else if (isArray(type)) { - typeString = "array"; - } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) { - typeString = - "<" + (getComponentNameFromType(type.type) || "Unknown") + " />"; - info = - " Did you accidentally export a JSX literal instead of a component?"; - } else { - typeString = typeof type; - } + var element = jsxDEV$1(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used. + // TODO: Drop this when these are no longer allowed as the type argument. + + if (element == null) { + return element; + } // Skip key warning if the type isn't valid since our key validation logic + // doesn't expect a non-string/function type and can throw confusing errors. + // We don't want exception behavior to differ between dev and prod. + // (Rendering will throw with a helpful message and as soon as the type is + // fixed, the key warnings will appear.) + + if (validType) { + var children = props.children; + + if (children !== undefined) { + if (isStaticChildren) { + if (isArray(children)) { + for (var i = 0; i < children.length; i++) { + validateChildKeys(children[i], type); + } - error( - "React.jsx: type is invalid -- expected a string (for " + - "built-in components) or a class/function (for composite " + - "components) but got: %s.%s", - typeString, - info - ); - } + if (Object.freeze) { + Object.freeze(children); + } + } else { + error( + "React.jsx: Static children should always be an array. " + + "You are likely explicitly calling React.jsxs or React.jsxDEV. " + + "Use the Babel transform instead." + ); + } + } else { + validateChildKeys(children, type); + } + } + } - var element = jsxDEV$1(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used. - // TODO: Drop this when these are no longer allowed as the type argument. + if (hasOwnProperty.call(props, "key")) { + var componentName = getComponentNameFromType(type); + var keys = Object.keys(props).filter(function (k) { + return k !== "key"; + }); + var beforeExample = + keys.length > 0 + ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" + : "{key: someKey}"; - if (element == null) { - return element; - } // Skip key warning if the type isn't valid since our key validation logic - // doesn't expect a non-string/function type and can throw confusing errors. - // We don't want exception behavior to differ between dev and prod. - // (Rendering will throw with a helpful message and as soon as the type is - // fixed, the key warnings will appear.) - - if (validType) { - var children = props.children; - - if (children !== undefined) { - if (isStaticChildren) { - if (isArray(children)) { - for (var i = 0; i < children.length; i++) { - validateChildKeys(children[i], type); - } + if (!didWarnAboutKeySpread[componentName + beforeExample]) { + var afterExample = + keys.length > 0 ? "{" + keys.join(": ..., ") + ": ...}" : "{}"; - if (Object.freeze) { - Object.freeze(children); - } - } else { error( - "React.jsx: Static children should always be an array. " + - "You are likely explicitly calling React.jsxs or React.jsxDEV. " + - "Use the Babel transform instead." + 'A props object containing a "key" prop is being spread into JSX:\n' + + " let props = %s;\n" + + " <%s {...props} />\n" + + "React keys must be passed directly to JSX without using spread:\n" + + " let props = %s;\n" + + " <%s key={someKey} {...props} />", + beforeExample, + componentName, + afterExample, + componentName ); + + didWarnAboutKeySpread[componentName + beforeExample] = true; } - } else { - validateChildKeys(children, type); } - } - } - - if (hasOwnProperty.call(props, "key")) { - var componentName = getComponentNameFromType(type); - var keys = Object.keys(props).filter(function (k) { - return k !== "key"; - }); - var beforeExample = - keys.length > 0 - ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" - : "{key: someKey}"; - if (!didWarnAboutKeySpread[componentName + beforeExample]) { - var afterExample = - keys.length > 0 ? "{" + keys.join(": ..., ") + ": ...}" : "{}"; + if (type === REACT_FRAGMENT_TYPE) { + validateFragmentProps(element); + } else { + validatePropTypes(element); + } - error( - 'A props object containing a "key" prop is being spread into JSX:\n' + - " let props = %s;\n" + - " <%s {...props} />\n" + - "React keys must be passed directly to JSX without using spread:\n" + - " let props = %s;\n" + - " <%s key={someKey} {...props} />", - beforeExample, - componentName, - afterExample, - componentName - ); + return element; + } + } // These two functions exist to still get child warnings in dev + // even with the prod transform. This means that jsxDEV is purely + // opt-in behavior for better messages but that we won't stop + // giving you warnings if you use production apis. - didWarnAboutKeySpread[componentName + beforeExample] = true; + function jsxWithValidationStatic(type, props, key) { + { + return jsxWithValidation(type, props, key, true); } } - - if (type === REACT_FRAGMENT_TYPE) { - validateFragmentProps(element); - } else { - validatePropTypes(element); + function jsxWithValidationDynamic(type, props, key) { + { + return jsxWithValidation(type, props, key, false); + } } - return element; - } -} // These two functions exist to still get child warnings in dev -// even with the prod transform. This means that jsxDEV is purely -// opt-in behavior for better messages but that we won't stop -// giving you warnings if you use production apis. - -function jsxWithValidationStatic(type, props, key) { - { - return jsxWithValidation(type, props, key, true); - } -} -function jsxWithValidationDynamic(type, props, key) { - { - return jsxWithValidation(type, props, key, false); - } -} - -var jsx = jsxWithValidationDynamic; // we may want to special case jsxs internally to take advantage of static children. -// for now we can ship identical prod functions - -var jsxs = jsxWithValidationStatic; -var jsxDEV = jsxWithValidation; - -exports.Children = Children; -exports.Component = Component; -exports.Fragment = REACT_FRAGMENT_TYPE; -exports.Profiler = REACT_PROFILER_TYPE; -exports.PureComponent = PureComponent; -exports.StrictMode = REACT_STRICT_MODE_TYPE; -exports.Suspense = REACT_SUSPENSE_TYPE; -exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = - ReactSharedInternals; -exports.cache = cache; -exports.cloneElement = cloneElement; -exports.createContext = createContext; -exports.createElement = createElement; -exports.createFactory = createFactory; -exports.createRef = createRef; -exports.experimental_useEffectEvent = useEffectEvent; -exports.forwardRef = forwardRef; -exports.isValidElement = isValidElement$1; -exports.jsx = jsx; -exports.jsxDEV = jsxDEV; -exports.jsxs = jsxs; -exports.lazy = lazy; -exports.memo = memo; -exports.startTransition = startTransition; -exports.unstable_Activity = REACT_OFFSCREEN_TYPE; -exports.unstable_Cache = REACT_CACHE_TYPE; -exports.unstable_DebugTracingMode = REACT_DEBUG_TRACING_MODE_TYPE; -exports.unstable_LegacyHidden = REACT_LEGACY_HIDDEN_TYPE; -exports.unstable_Scope = REACT_SCOPE_TYPE; -exports.unstable_SuspenseList = REACT_SUSPENSE_LIST_TYPE; -exports.unstable_TracingMarker = REACT_TRACING_MARKER_TYPE; -exports.unstable_act = act; -exports.unstable_getCacheForType = getCacheForType; -exports.unstable_getCacheSignal = getCacheSignal; -exports.unstable_useCacheRefresh = useCacheRefresh; -exports.unstable_useMemoCache = useMemoCache; -exports.use = use; -exports.useCallback = useCallback; -exports.useContext = useContext; -exports.useDebugValue = useDebugValue; -exports.useDeferredValue = useDeferredValue; -exports.useEffect = useEffect; -exports.useId = useId; -exports.useImperativeHandle = useImperativeHandle; -exports.useInsertionEffect = useInsertionEffect; -exports.useLayoutEffect = useLayoutEffect; -exports.useMemo = useMemo; -exports.useOptimistic = useOptimistic; -exports.useReducer = useReducer; -exports.useRef = useRef; -exports.useState = useState; -exports.useSyncExternalStore = useSyncExternalStore; -exports.useTransition = useTransition; -exports.version = ReactVersion; - - /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ -if ( - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop === - 'function' -) { - __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error()); -} - + var jsx = jsxWithValidationDynamic; // we may want to special case jsxs internally to take advantage of static children. + // for now we can ship identical prod functions + + var jsxs = jsxWithValidationStatic; + var jsxDEV = jsxWithValidation; + + exports.Children = Children; + exports.Component = Component; + exports.Fragment = REACT_FRAGMENT_TYPE; + exports.Profiler = REACT_PROFILER_TYPE; + exports.PureComponent = PureComponent; + exports.StrictMode = REACT_STRICT_MODE_TYPE; + exports.Suspense = REACT_SUSPENSE_TYPE; + exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = + ReactSharedInternals; + exports.cache = cache; + exports.cloneElement = cloneElement; + exports.createContext = createContext; + exports.createElement = createElement; + exports.createFactory = createFactory; + exports.createRef = createRef; + exports.experimental_useEffectEvent = useEffectEvent; + exports.forwardRef = forwardRef; + exports.isValidElement = isValidElement$1; + exports.jsx = jsx; + exports.jsxDEV = jsxDEV; + exports.jsxs = jsxs; + exports.lazy = lazy; + exports.memo = memo; + exports.startTransition = startTransition; + exports.unstable_Activity = REACT_OFFSCREEN_TYPE; + exports.unstable_Cache = REACT_CACHE_TYPE; + exports.unstable_DebugTracingMode = REACT_DEBUG_TRACING_MODE_TYPE; + exports.unstable_LegacyHidden = REACT_LEGACY_HIDDEN_TYPE; + exports.unstable_Scope = REACT_SCOPE_TYPE; + exports.unstable_SuspenseList = REACT_SUSPENSE_LIST_TYPE; + exports.unstable_TracingMarker = REACT_TRACING_MARKER_TYPE; + exports.unstable_act = act; + exports.unstable_getCacheForType = getCacheForType; + exports.unstable_getCacheSignal = getCacheSignal; + exports.unstable_useCacheRefresh = useCacheRefresh; + exports.unstable_useMemoCache = useMemoCache; + exports.use = use; + exports.useCallback = useCallback; + exports.useContext = useContext; + exports.useDebugValue = useDebugValue; + exports.useDeferredValue = useDeferredValue; + exports.useEffect = useEffect; + exports.useId = useId; + exports.useImperativeHandle = useImperativeHandle; + exports.useInsertionEffect = useInsertionEffect; + exports.useLayoutEffect = useLayoutEffect; + exports.useMemo = useMemo; + exports.useOptimistic = useOptimistic; + exports.useReducer = useReducer; + exports.useRef = useRef; + exports.useState = useState; + exports.useSyncExternalStore = useSyncExternalStore; + exports.useTransition = useTransition; + exports.version = ReactVersion; + /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ + if ( + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined" && + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop === + "function" + ) { + __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error()); + } })(); } diff --git a/compiled/facebook-www/React-dev.modern.js b/compiled/facebook-www/React-dev.modern.js index 2e1424b89db10..02602a464c63e 100644 --- a/compiled/facebook-www/React-dev.modern.js +++ b/compiled/facebook-www/React-dev.modern.js @@ -1,4 +1,5 @@ /** + * @preserve * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the @@ -10,4076 +11,4126 @@ * @preserve-invariant-messages */ -'use strict'; +"use strict"; if (__DEV__) { - (function() { + (function () { + "use strict"; - 'use strict'; + /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ + if ( + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined" && + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart === + "function" + ) { + __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); + } + var ReactVersion = "18.3.0-www-modern-f1567e75"; + + // ATTENTION + // When adding new symbols to this file, + // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' + // The Symbol used to tag the ReactElement-like types. + var REACT_ELEMENT_TYPE = Symbol.for("react.element"); + var REACT_PORTAL_TYPE = Symbol.for("react.portal"); + var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); + var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); + var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); + var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); + var REACT_CONTEXT_TYPE = Symbol.for("react.context"); + var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); + var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); + var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); + var REACT_MEMO_TYPE = Symbol.for("react.memo"); + var REACT_LAZY_TYPE = Symbol.for("react.lazy"); + var REACT_SCOPE_TYPE = Symbol.for("react.scope"); + var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); + var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); + var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); + var REACT_CACHE_TYPE = Symbol.for("react.cache"); + var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); + var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; + var FAUX_ITERATOR_SYMBOL = "@@iterator"; + function getIteratorFn(maybeIterable) { + if (maybeIterable === null || typeof maybeIterable !== "object") { + return null; + } -/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ -if ( - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart === - 'function' -) { - __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); -} - "use strict"; - -var ReactVersion = "18.3.0-www-modern-c0649ecc"; - -// ATTENTION -// When adding new symbols to this file, -// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' -// The Symbol used to tag the ReactElement-like types. -var REACT_ELEMENT_TYPE = Symbol.for("react.element"); -var REACT_PORTAL_TYPE = Symbol.for("react.portal"); -var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); -var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); -var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); -var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); -var REACT_CONTEXT_TYPE = Symbol.for("react.context"); -var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); -var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); -var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); -var REACT_MEMO_TYPE = Symbol.for("react.memo"); -var REACT_LAZY_TYPE = Symbol.for("react.lazy"); -var REACT_SCOPE_TYPE = Symbol.for("react.scope"); -var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); -var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); -var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); -var REACT_CACHE_TYPE = Symbol.for("react.cache"); -var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); -var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; -var FAUX_ITERATOR_SYMBOL = "@@iterator"; -function getIteratorFn(maybeIterable) { - if (maybeIterable === null || typeof maybeIterable !== "object") { - return null; - } - - var maybeIterator = - (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || - maybeIterable[FAUX_ITERATOR_SYMBOL]; - - if (typeof maybeIterator === "function") { - return maybeIterator; - } - - return null; -} + var maybeIterator = + (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || + maybeIterable[FAUX_ITERATOR_SYMBOL]; -// This refers to a WWW module. -var warningWWW = require("warning"); -function warn(format) { - { - { - for ( - var _len = arguments.length, - args = new Array(_len > 1 ? _len - 1 : 0), - _key = 1; - _key < _len; - _key++ - ) { - args[_key - 1] = arguments[_key]; + if (typeof maybeIterator === "function") { + return maybeIterator; } - printWarning("warn", format, args); + return null; } - } -} -function error(format) { - { - { - for ( - var _len2 = arguments.length, - args = new Array(_len2 > 1 ? _len2 - 1 : 0), - _key2 = 1; - _key2 < _len2; - _key2++ - ) { - args[_key2 - 1] = arguments[_key2]; + + // This refers to a WWW module. + var warningWWW = require("warning"); + function warn(format) { + { + { + for ( + var _len = arguments.length, + args = new Array(_len > 1 ? _len - 1 : 0), + _key = 1; + _key < _len; + _key++ + ) { + args[_key - 1] = arguments[_key]; + } + + printWarning("warn", format, args); + } } + } + function error(format) { + { + { + for ( + var _len2 = arguments.length, + args = new Array(_len2 > 1 ? _len2 - 1 : 0), + _key2 = 1; + _key2 < _len2; + _key2++ + ) { + args[_key2 - 1] = arguments[_key2]; + } - printWarning("error", format, args); + printWarning("error", format, args); + } + } } - } -} -function printWarning(level, format, args) { - { - var React = require("react"); + function printWarning(level, format, args) { + { + var React = require("react"); + + var ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. - var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. + if (ReactSharedInternals != null) { + var ReactDebugCurrentFrame = + ReactSharedInternals.ReactDebugCurrentFrame; + var stack = ReactDebugCurrentFrame.getStackAddendum(); - if (ReactSharedInternals != null) { - var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - var stack = ReactDebugCurrentFrame.getStackAddendum(); + if (stack !== "") { + format += "%s"; + args.push(stack); + } + } // TODO: don't ignore level and pass it down somewhere too. - if (stack !== "") { - format += "%s"; - args.push(stack); + args.unshift(format); + args.unshift(false); + warningWWW.apply(null, args); } - } // TODO: don't ignore level and pass it down somewhere too. + } - args.unshift(format); - args.unshift(false); - warningWWW.apply(null, args); - } -} + var didWarnStateUpdateForUnmountedComponent = {}; -var didWarnStateUpdateForUnmountedComponent = {}; + function warnNoop(publicInstance, callerName) { + { + var _constructor = publicInstance.constructor; + var componentName = + (_constructor && (_constructor.displayName || _constructor.name)) || + "ReactClass"; + var warningKey = componentName + "." + callerName; + + if (didWarnStateUpdateForUnmountedComponent[warningKey]) { + return; + } -function warnNoop(publicInstance, callerName) { - { - var _constructor = publicInstance.constructor; - var componentName = - (_constructor && (_constructor.displayName || _constructor.name)) || - "ReactClass"; - var warningKey = componentName + "." + callerName; + error( + "Can't call %s on a component that is not yet mounted. " + + "This is a no-op, but it might indicate a bug in your application. " + + "Instead, assign to `this.state` directly or define a `state = {};` " + + "class property with the desired state in the %s component.", + callerName, + componentName + ); - if (didWarnStateUpdateForUnmountedComponent[warningKey]) { - return; + didWarnStateUpdateForUnmountedComponent[warningKey] = true; + } } + /** + * This is the abstract API for an update queue. + */ + + var ReactNoopUpdateQueue = { + /** + * Checks whether or not this composite component is mounted. + * @param {ReactClass} publicInstance The instance we want to test. + * @return {boolean} True if mounted, false otherwise. + * @protected + * @final + */ + isMounted: function (publicInstance) { + return false; + }, - error( - "Can't call %s on a component that is not yet mounted. " + - "This is a no-op, but it might indicate a bug in your application. " + - "Instead, assign to `this.state` directly or define a `state = {};` " + - "class property with the desired state in the %s component.", - callerName, - componentName - ); + /** + * Forces an update. This should only be invoked when it is known with + * certainty that we are **not** in a DOM transaction. + * + * You may want to call this when you know that some deeper aspect of the + * component's state has changed but `setState` was not called. + * + * This will not invoke `shouldComponentUpdate`, but it will invoke + * `componentWillUpdate` and `componentDidUpdate`. + * + * @param {ReactClass} publicInstance The instance that should rerender. + * @param {?function} callback Called after component is updated. + * @param {?string} callerName name of the calling function in the public API. + * @internal + */ + enqueueForceUpdate: function (publicInstance, callback, callerName) { + warnNoop(publicInstance, "forceUpdate"); + }, - didWarnStateUpdateForUnmountedComponent[warningKey] = true; - } -} -/** - * This is the abstract API for an update queue. - */ + /** + * Replaces all of the state. Always use this or `setState` to mutate state. + * You should treat `this.state` as immutable. + * + * There is no guarantee that `this.state` will be immediately updated, so + * accessing `this.state` after calling this method may return the old value. + * + * @param {ReactClass} publicInstance The instance that should rerender. + * @param {object} completeState Next state. + * @param {?function} callback Called after component is updated. + * @param {?string} callerName name of the calling function in the public API. + * @internal + */ + enqueueReplaceState: function ( + publicInstance, + completeState, + callback, + callerName + ) { + warnNoop(publicInstance, "replaceState"); + }, -var ReactNoopUpdateQueue = { - /** - * Checks whether or not this composite component is mounted. - * @param {ReactClass} publicInstance The instance we want to test. - * @return {boolean} True if mounted, false otherwise. - * @protected - * @final - */ - isMounted: function (publicInstance) { - return false; - }, - - /** - * Forces an update. This should only be invoked when it is known with - * certainty that we are **not** in a DOM transaction. - * - * You may want to call this when you know that some deeper aspect of the - * component's state has changed but `setState` was not called. - * - * This will not invoke `shouldComponentUpdate`, but it will invoke - * `componentWillUpdate` and `componentDidUpdate`. - * - * @param {ReactClass} publicInstance The instance that should rerender. - * @param {?function} callback Called after component is updated. - * @param {?string} callerName name of the calling function in the public API. - * @internal - */ - enqueueForceUpdate: function (publicInstance, callback, callerName) { - warnNoop(publicInstance, "forceUpdate"); - }, - - /** - * Replaces all of the state. Always use this or `setState` to mutate state. - * You should treat `this.state` as immutable. - * - * There is no guarantee that `this.state` will be immediately updated, so - * accessing `this.state` after calling this method may return the old value. - * - * @param {ReactClass} publicInstance The instance that should rerender. - * @param {object} completeState Next state. - * @param {?function} callback Called after component is updated. - * @param {?string} callerName name of the calling function in the public API. - * @internal - */ - enqueueReplaceState: function ( - publicInstance, - completeState, - callback, - callerName - ) { - warnNoop(publicInstance, "replaceState"); - }, - - /** - * Sets a subset of the state. This only exists because _pendingState is - * internal. This provides a merging strategy that is not available to deep - * properties which is confusing. TODO: Expose pendingState or don't use it - * during the merge. - * - * @param {ReactClass} publicInstance The instance that should rerender. - * @param {object} partialState Next partial state to be merged with state. - * @param {?function} callback Called after component is updated. - * @param {?string} Name of the calling function in the public API. - * @internal - */ - enqueueSetState: function ( - publicInstance, - partialState, - callback, - callerName - ) { - warnNoop(publicInstance, "setState"); - } -}; - -var assign = Object.assign; - -var emptyObject = {}; - -{ - Object.freeze(emptyObject); -} -/** - * Base class helpers for the updating state of a component. - */ + /** + * Sets a subset of the state. This only exists because _pendingState is + * internal. This provides a merging strategy that is not available to deep + * properties which is confusing. TODO: Expose pendingState or don't use it + * during the merge. + * + * @param {ReactClass} publicInstance The instance that should rerender. + * @param {object} partialState Next partial state to be merged with state. + * @param {?function} callback Called after component is updated. + * @param {?string} Name of the calling function in the public API. + * @internal + */ + enqueueSetState: function ( + publicInstance, + partialState, + callback, + callerName + ) { + warnNoop(publicInstance, "setState"); + } + }; -function Component(props, context, updater) { - this.props = props; - this.context = context; // If a component has string refs, we will assign a different object later. + var assign = Object.assign; - this.refs = emptyObject; // We initialize the default updater but the real one gets injected by the - // renderer. + var emptyObject = {}; - this.updater = updater || ReactNoopUpdateQueue; -} + { + Object.freeze(emptyObject); + } + /** + * Base class helpers for the updating state of a component. + */ -Component.prototype.isReactComponent = {}; -/** - * Sets a subset of the state. Always use this to mutate - * state. You should treat `this.state` as immutable. - * - * There is no guarantee that `this.state` will be immediately updated, so - * accessing `this.state` after calling this method may return the old value. - * - * There is no guarantee that calls to `setState` will run synchronously, - * as they may eventually be batched together. You can provide an optional - * callback that will be executed when the call to setState is actually - * completed. - * - * When a function is provided to setState, it will be called at some point in - * the future (not synchronously). It will be called with the up to date - * component arguments (state, props, context). These values can be different - * from this.* because your function may be called after receiveProps but before - * shouldComponentUpdate, and this new state, props, and context will not yet be - * assigned to this. - * - * @param {object|function} partialState Next partial state or function to - * produce next partial state to be merged with current state. - * @param {?function} callback Called after state is updated. - * @final - * @protected - */ + function Component(props, context, updater) { + this.props = props; + this.context = context; // If a component has string refs, we will assign a different object later. -Component.prototype.setState = function (partialState, callback) { - if ( - typeof partialState !== "object" && - typeof partialState !== "function" && - partialState != null - ) { - throw new Error( - "setState(...): takes an object of state variables to update or a " + - "function which returns an object of state variables." - ); - } - - this.updater.enqueueSetState(this, partialState, callback, "setState"); -}; -/** - * Forces an update. This should only be invoked when it is known with - * certainty that we are **not** in a DOM transaction. - * - * You may want to call this when you know that some deeper aspect of the - * component's state has changed but `setState` was not called. - * - * This will not invoke `shouldComponentUpdate`, but it will invoke - * `componentWillUpdate` and `componentDidUpdate`. - * - * @param {?function} callback Called after update is complete. - * @final - * @protected - */ + this.refs = emptyObject; // We initialize the default updater but the real one gets injected by the + // renderer. -Component.prototype.forceUpdate = function (callback) { - this.updater.enqueueForceUpdate(this, callback, "forceUpdate"); -}; -/** - * Deprecated APIs. These APIs used to exist on classic React classes but since - * we would like to deprecate them, we're not going to move them over to this - * modern base class. Instead, we define a getter that warns if it's accessed. - */ + this.updater = updater || ReactNoopUpdateQueue; + } -{ - var deprecatedAPIs = { - isMounted: [ - "isMounted", - "Instead, make sure to clean up subscriptions and pending requests in " + - "componentWillUnmount to prevent memory leaks." - ], - replaceState: [ - "replaceState", - "Refactor your code to use setState instead (see " + - "https://github.com/facebook/react/issues/3236)." - ] - }; - - var defineDeprecationWarning = function (methodName, info) { - Object.defineProperty(Component.prototype, methodName, { - get: function () { - warn( - "%s(...) is deprecated in plain JavaScript React classes. %s", - info[0], - info[1] + Component.prototype.isReactComponent = {}; + /** + * Sets a subset of the state. Always use this to mutate + * state. You should treat `this.state` as immutable. + * + * There is no guarantee that `this.state` will be immediately updated, so + * accessing `this.state` after calling this method may return the old value. + * + * There is no guarantee that calls to `setState` will run synchronously, + * as they may eventually be batched together. You can provide an optional + * callback that will be executed when the call to setState is actually + * completed. + * + * When a function is provided to setState, it will be called at some point in + * the future (not synchronously). It will be called with the up to date + * component arguments (state, props, context). These values can be different + * from this.* because your function may be called after receiveProps but before + * shouldComponentUpdate, and this new state, props, and context will not yet be + * assigned to this. + * + * @param {object|function} partialState Next partial state or function to + * produce next partial state to be merged with current state. + * @param {?function} callback Called after state is updated. + * @final + * @protected + */ + + Component.prototype.setState = function (partialState, callback) { + if ( + typeof partialState !== "object" && + typeof partialState !== "function" && + partialState != null + ) { + throw new Error( + "setState(...): takes an object of state variables to update or a " + + "function which returns an object of state variables." ); - - return undefined; } - }); - }; - for (var fnName in deprecatedAPIs) { - if (deprecatedAPIs.hasOwnProperty(fnName)) { - defineDeprecationWarning(fnName, deprecatedAPIs[fnName]); - } - } -} + this.updater.enqueueSetState(this, partialState, callback, "setState"); + }; + /** + * Forces an update. This should only be invoked when it is known with + * certainty that we are **not** in a DOM transaction. + * + * You may want to call this when you know that some deeper aspect of the + * component's state has changed but `setState` was not called. + * + * This will not invoke `shouldComponentUpdate`, but it will invoke + * `componentWillUpdate` and `componentDidUpdate`. + * + * @param {?function} callback Called after update is complete. + * @final + * @protected + */ + + Component.prototype.forceUpdate = function (callback) { + this.updater.enqueueForceUpdate(this, callback, "forceUpdate"); + }; + /** + * Deprecated APIs. These APIs used to exist on classic React classes but since + * we would like to deprecate them, we're not going to move them over to this + * modern base class. Instead, we define a getter that warns if it's accessed. + */ -function ComponentDummy() {} + { + var deprecatedAPIs = { + isMounted: [ + "isMounted", + "Instead, make sure to clean up subscriptions and pending requests in " + + "componentWillUnmount to prevent memory leaks." + ], + replaceState: [ + "replaceState", + "Refactor your code to use setState instead (see " + + "https://github.com/facebook/react/issues/3236)." + ] + }; -ComponentDummy.prototype = Component.prototype; -/** - * Convenience component with default shallow equality check for sCU. - */ + var defineDeprecationWarning = function (methodName, info) { + Object.defineProperty(Component.prototype, methodName, { + get: function () { + warn( + "%s(...) is deprecated in plain JavaScript React classes. %s", + info[0], + info[1] + ); + + return undefined; + } + }); + }; -function PureComponent(props, context, updater) { - this.props = props; - this.context = context; // If a component has string refs, we will assign a different object later. + for (var fnName in deprecatedAPIs) { + if (deprecatedAPIs.hasOwnProperty(fnName)) { + defineDeprecationWarning(fnName, deprecatedAPIs[fnName]); + } + } + } - this.refs = emptyObject; - this.updater = updater || ReactNoopUpdateQueue; -} + function ComponentDummy() {} -var pureComponentPrototype = (PureComponent.prototype = new ComponentDummy()); -pureComponentPrototype.constructor = PureComponent; // Avoid an extra prototype jump for these methods. + ComponentDummy.prototype = Component.prototype; + /** + * Convenience component with default shallow equality check for sCU. + */ -assign(pureComponentPrototype, Component.prototype); -pureComponentPrototype.isPureReactComponent = true; + function PureComponent(props, context, updater) { + this.props = props; + this.context = context; // If a component has string refs, we will assign a different object later. -// an immutable object with a single mutable value -function createRef() { - var refObject = { - current: null - }; + this.refs = emptyObject; + this.updater = updater || ReactNoopUpdateQueue; + } - { - Object.seal(refObject); - } + var pureComponentPrototype = (PureComponent.prototype = + new ComponentDummy()); + pureComponentPrototype.constructor = PureComponent; // Avoid an extra prototype jump for these methods. - return refObject; -} + assign(pureComponentPrototype, Component.prototype); + pureComponentPrototype.isPureReactComponent = true; -var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare + // an immutable object with a single mutable value + function createRef() { + var refObject = { + current: null + }; -function isArray(a) { - return isArrayImpl(a); -} + { + Object.seal(refObject); + } -/* - * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol - * and Temporal.* types. See https://github.com/facebook/react/pull/22064. - * - * The functions in this module will throw an easier-to-understand, - * easier-to-debug exception with a clear errors message message explaining the - * problem. (Instead of a confusing exception thrown inside the implementation - * of the `value` object). - */ -// $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. -function typeName(value) { - { - // toStringTag is needed for namespaced types like Temporal.Instant - var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; - var type = - (hasToStringTag && value[Symbol.toStringTag]) || - value.constructor.name || - "Object"; // $FlowFixMe[incompatible-return] - - return type; - } -} // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - -function willCoercionThrow(value) { - { - try { - testStringCoercion(value); - return false; - } catch (e) { - return true; + return refObject; } - } -} -function testStringCoercion(value) { - // If you ended up here by following an exception call stack, here's what's - // happened: you supplied an object or symbol value to React (as a prop, key, - // DOM attribute, CSS property, string ref, etc.) and when React tried to - // coerce it to a string using `'' + value`, an exception was thrown. - // - // The most common types that will cause this exception are `Symbol` instances - // and Temporal objects like `Temporal.Instant`. But any object that has a - // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this - // exception. (Library authors do this to prevent users from using built-in - // numeric operators like `+` or comparison operators like `>=` because custom - // methods are needed to perform accurate arithmetic or comparison.) - // - // To fix the problem, coerce this object or symbol value to a string before - // passing it to React. The most reliable way is usually `String(value)`. - // - // To find which value is throwing, check the browser or debugger console. - // Before this exception was thrown, there should be `console.error` output - // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the - // problem and how that type was used: key, atrribute, input value prop, etc. - // In most cases, this console output also shows the component and its - // ancestor components where the exception happened. - // - // eslint-disable-next-line react-internal/safe-string-coercion - return "" + value; -} -function checkKeyStringCoercion(value) { - { - if (willCoercionThrow(value)) { - error( - "The provided key is an unsupported type %s." + - " This value must be coerced to a string before using it here.", - typeName(value) - ); + var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + function isArray(a) { + return isArrayImpl(a); } - } -} -// Re-export dynamic flags from the www version. -var dynamicFeatureFlags = require("ReactFeatureFlags"); - -var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, - enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing; -// On WWW, true is used for a new modern build. - -function getWrappedName(outerType, innerType, wrapperName) { - var displayName = outerType.displayName; - - if (displayName) { - return displayName; - } - - var functionName = innerType.displayName || innerType.name || ""; - return functionName !== "" - ? wrapperName + "(" + functionName + ")" - : wrapperName; -} // Keep in sync with react-reconciler/getComponentNameFromFiber - -function getContextName(type) { - return type.displayName || "Context"; -} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. - -function getComponentNameFromType(type) { - if (type == null) { - // Host root, text node or just invalid type. - return null; - } - - { - if (typeof type.tag === "number") { - error( - "Received an unexpected object in getComponentNameFromType(). " + - "This is likely a bug in React. Please file an issue." - ); + /* + * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol + * and Temporal.* types. See https://github.com/facebook/react/pull/22064. + * + * The functions in this module will throw an easier-to-understand, + * easier-to-debug exception with a clear errors message message explaining the + * problem. (Instead of a confusing exception thrown inside the implementation + * of the `value` object). + */ + // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. + function typeName(value) { + { + // toStringTag is needed for namespaced types like Temporal.Instant + var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; + var type = + (hasToStringTag && value[Symbol.toStringTag]) || + value.constructor.name || + "Object"; // $FlowFixMe[incompatible-return] + + return type; + } + } // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. + + function willCoercionThrow(value) { + { + try { + testStringCoercion(value); + return false; + } catch (e) { + return true; + } + } } - } - if (typeof type === "function") { - return type.displayName || type.name || null; - } + function testStringCoercion(value) { + // If you ended up here by following an exception call stack, here's what's + // happened: you supplied an object or symbol value to React (as a prop, key, + // DOM attribute, CSS property, string ref, etc.) and when React tried to + // coerce it to a string using `'' + value`, an exception was thrown. + // + // The most common types that will cause this exception are `Symbol` instances + // and Temporal objects like `Temporal.Instant`. But any object that has a + // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this + // exception. (Library authors do this to prevent users from using built-in + // numeric operators like `+` or comparison operators like `>=` because custom + // methods are needed to perform accurate arithmetic or comparison.) + // + // To fix the problem, coerce this object or symbol value to a string before + // passing it to React. The most reliable way is usually `String(value)`. + // + // To find which value is throwing, check the browser or debugger console. + // Before this exception was thrown, there should be `console.error` output + // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the + // problem and how that type was used: key, atrribute, input value prop, etc. + // In most cases, this console output also shows the component and its + // ancestor components where the exception happened. + // + // eslint-disable-next-line react-internal/safe-string-coercion + return "" + value; + } + function checkKeyStringCoercion(value) { + { + if (willCoercionThrow(value)) { + error( + "The provided key is an unsupported type %s." + + " This value must be coerced to a string before using it here.", + typeName(value) + ); - if (typeof type === "string") { - return type; - } + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + } + } + } - switch (type) { - case REACT_FRAGMENT_TYPE: - return "Fragment"; + // Re-export dynamic flags from the www version. + var dynamicFeatureFlags = require("ReactFeatureFlags"); - case REACT_PORTAL_TYPE: - return "Portal"; + var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, + enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing; + // On WWW, true is used for a new modern build. - case REACT_PROFILER_TYPE: - return "Profiler"; + function getWrappedName(outerType, innerType, wrapperName) { + var displayName = outerType.displayName; - case REACT_STRICT_MODE_TYPE: - return "StrictMode"; + if (displayName) { + return displayName; + } - case REACT_SUSPENSE_TYPE: - return "Suspense"; + var functionName = innerType.displayName || innerType.name || ""; + return functionName !== "" + ? wrapperName + "(" + functionName + ")" + : wrapperName; + } // Keep in sync with react-reconciler/getComponentNameFromFiber - case REACT_SUSPENSE_LIST_TYPE: - return "SuspenseList"; + function getContextName(type) { + return type.displayName || "Context"; + } // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. - case REACT_CACHE_TYPE: { - return "Cache"; - } + function getComponentNameFromType(type) { + if (type == null) { + // Host root, text node or just invalid type. + return null; + } - // Fall through + { + if (typeof type.tag === "number") { + error( + "Received an unexpected object in getComponentNameFromType(). " + + "This is likely a bug in React. Please file an issue." + ); + } + } - case REACT_TRACING_MARKER_TYPE: - if (enableTransitionTracing) { - return "TracingMarker"; + if (typeof type === "function") { + return type.displayName || type.name || null; } - } - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_CONTEXT_TYPE: - var context = type; - return getContextName(context) + ".Consumer"; + if (typeof type === "string") { + return type; + } - case REACT_PROVIDER_TYPE: - var provider = type; - return getContextName(provider._context) + ".Provider"; + switch (type) { + case REACT_FRAGMENT_TYPE: + return "Fragment"; - case REACT_FORWARD_REF_TYPE: - return getWrappedName(type, type.render, "ForwardRef"); + case REACT_PORTAL_TYPE: + return "Portal"; - case REACT_MEMO_TYPE: - var outerName = type.displayName || null; + case REACT_PROFILER_TYPE: + return "Profiler"; - if (outerName !== null) { - return outerName; - } + case REACT_STRICT_MODE_TYPE: + return "StrictMode"; - return getComponentNameFromType(type.type) || "Memo"; + case REACT_SUSPENSE_TYPE: + return "Suspense"; - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + case REACT_SUSPENSE_LIST_TYPE: + return "SuspenseList"; - try { - return getComponentNameFromType(init(payload)); - } catch (x) { - return null; + case REACT_CACHE_TYPE: { + return "Cache"; } + + // Fall through + + case REACT_TRACING_MARKER_TYPE: + if (enableTransitionTracing) { + return "TracingMarker"; + } } - } - } - return null; -} + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_CONTEXT_TYPE: + var context = type; + return getContextName(context) + ".Consumer"; -// $FlowFixMe[method-unbinding] -var hasOwnProperty = Object.prototype.hasOwnProperty; + case REACT_PROVIDER_TYPE: + var provider = type; + return getContextName(provider._context) + ".Provider"; -/** - * Keeps track of the current owner. - * - * The current owner is the component who should own any components that are - * currently being constructed. - */ -var ReactCurrentOwner$2 = { - /** - * @internal - * @type {ReactComponent} - */ - current: null -}; - -var RESERVED_PROPS$1 = { - key: true, - ref: true, - __self: true, - __source: true -}; -var specialPropKeyWarningShown$1, - specialPropRefWarningShown$1, - didWarnAboutStringRefs$1; - -{ - didWarnAboutStringRefs$1 = {}; -} + case REACT_FORWARD_REF_TYPE: + return getWrappedName(type, type.render, "ForwardRef"); -function hasValidRef$1(config) { - { - if (hasOwnProperty.call(config, "ref")) { - var getter = Object.getOwnPropertyDescriptor(config, "ref").get; + case REACT_MEMO_TYPE: + var outerName = type.displayName || null; - if (getter && getter.isReactWarning) { - return false; - } - } - } + if (outerName !== null) { + return outerName; + } - return config.ref !== undefined; -} + return getComponentNameFromType(type.type) || "Memo"; -function hasValidKey$1(config) { - { - if (hasOwnProperty.call(config, "key")) { - var getter = Object.getOwnPropertyDescriptor(config, "key").get; + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - if (getter && getter.isReactWarning) { - return false; + try { + return getComponentNameFromType(init(payload)); + } catch (x) { + return null; + } + } + } } + + return null; } - } - return config.key !== undefined; -} + // $FlowFixMe[method-unbinding] + var hasOwnProperty = Object.prototype.hasOwnProperty; + + /** + * Keeps track of the current owner. + * + * The current owner is the component who should own any components that are + * currently being constructed. + */ + var ReactCurrentOwner$2 = { + /** + * @internal + * @type {ReactComponent} + */ + current: null + }; + + var RESERVED_PROPS$1 = { + key: true, + ref: true, + __self: true, + __source: true + }; + var specialPropKeyWarningShown$1, + specialPropRefWarningShown$1, + didWarnAboutStringRefs$1; -function defineKeyPropWarningGetter$1(props, displayName) { - var warnAboutAccessingKey = function () { { - if (!specialPropKeyWarningShown$1) { - specialPropKeyWarningShown$1 = true; + didWarnAboutStringRefs$1 = {}; + } - error( - "%s: `key` is not a prop. Trying to access it will result " + - "in `undefined` being returned. If you need to access the same " + - "value within the child component, you should pass it as a different " + - "prop. (https://reactjs.org/link/special-props)", - displayName - ); + function hasValidRef$1(config) { + { + if (hasOwnProperty.call(config, "ref")) { + var getter = Object.getOwnPropertyDescriptor(config, "ref").get; + + if (getter && getter.isReactWarning) { + return false; + } + } } - } - }; - warnAboutAccessingKey.isReactWarning = true; - Object.defineProperty(props, "key", { - get: warnAboutAccessingKey, - configurable: true - }); -} + return config.ref !== undefined; + } -function defineRefPropWarningGetter$1(props, displayName) { - var warnAboutAccessingRef = function () { - { - if (!specialPropRefWarningShown$1) { - specialPropRefWarningShown$1 = true; + function hasValidKey$1(config) { + { + if (hasOwnProperty.call(config, "key")) { + var getter = Object.getOwnPropertyDescriptor(config, "key").get; - error( - "%s: `ref` is not a prop. Trying to access it will result " + - "in `undefined` being returned. If you need to access the same " + - "value within the child component, you should pass it as a different " + - "prop. (https://reactjs.org/link/special-props)", - displayName - ); + if (getter && getter.isReactWarning) { + return false; + } + } } - } - }; - warnAboutAccessingRef.isReactWarning = true; - Object.defineProperty(props, "ref", { - get: warnAboutAccessingRef, - configurable: true - }); -} + return config.key !== undefined; + } -function warnIfStringRefCannotBeAutoConverted$1(config) { - { - if ( - typeof config.ref === "string" && - ReactCurrentOwner$2.current && - config.__self && - ReactCurrentOwner$2.current.stateNode !== config.__self - ) { - var componentName = getComponentNameFromType( - ReactCurrentOwner$2.current.type - ); + function defineKeyPropWarningGetter$1(props, displayName) { + var warnAboutAccessingKey = function () { + { + if (!specialPropKeyWarningShown$1) { + specialPropKeyWarningShown$1 = true; - if (!didWarnAboutStringRefs$1[componentName]) { - error( - 'Component "%s" contains the string ref "%s". ' + - "Support for string refs will be removed in a future major release. " + - "This case cannot be automatically converted to an arrow function. " + - "We ask you to manually fix this case by using useRef() or createRef() instead. " + - "Learn more about using refs safely here: " + - "https://reactjs.org/link/strict-mode-string-ref", - componentName, - config.ref - ); + error( + "%s: `key` is not a prop. Trying to access it will result " + + "in `undefined` being returned. If you need to access the same " + + "value within the child component, you should pass it as a different " + + "prop. (https://reactjs.org/link/special-props)", + displayName + ); + } + } + }; - didWarnAboutStringRefs$1[componentName] = true; - } + warnAboutAccessingKey.isReactWarning = true; + Object.defineProperty(props, "key", { + get: warnAboutAccessingKey, + configurable: true + }); } - } -} -/** - * Factory method to create a new React element. This no longer adheres to - * the class pattern, so do not use new to call it. Also, instanceof check - * will not work. Instead test $$typeof field against Symbol.for('react.element') to check - * if something is a React Element. - * - * @param {*} type - * @param {*} props - * @param {*} key - * @param {string|object} ref - * @param {*} owner - * @param {*} self A *temporary* helper to detect places where `this` is - * different from the `owner` when React.createElement is called, so that we - * can warn. We want to get rid of owner and replace string `ref`s with arrow - * functions, and as long as `this` and owner are the same, there will be no - * change in behavior. - * @param {*} source An annotation object (added by a transpiler or otherwise) - * indicating filename, line number, and/or other information. - * @internal - */ -function ReactElement$1(type, key, ref, self, source, owner, props) { - var element = { - // This tag allows us to uniquely identify this as a React Element - $$typeof: REACT_ELEMENT_TYPE, - // Built-in properties that belong on the element - type: type, - key: key, - ref: ref, - props: props, - // Record the component responsible for creating this element. - _owner: owner - }; - - { - // The validation flag is currently mutative. We put it on - // an external backing store so that we can freeze the whole object. - // This can be replaced with a WeakMap once they are implemented in - // commonly used development environments. - element._store = {}; // To make comparing ReactElements easier for testing purposes, we make - // the validation flag non-enumerable (where possible, which should - // include every environment we run tests in), so the test framework - // ignores it. - - Object.defineProperty(element._store, "validated", { - configurable: false, - enumerable: false, - writable: true, - value: false - }); // self and source are DEV only properties. - - Object.defineProperty(element, "_self", { - configurable: false, - enumerable: false, - writable: false, - value: self - }); // Two elements created in two different places should be considered - // equal for testing purposes and therefore we hide it from enumeration. - - Object.defineProperty(element, "_source", { - configurable: false, - enumerable: false, - writable: false, - value: source - }); - - if (Object.freeze) { - Object.freeze(element.props); - Object.freeze(element); - } - } - - return element; -} -/** - * Create and return a new ReactElement of the given type. - * See https://reactjs.org/docs/react-api.html#createelement - */ - -function createElement$1(type, config, children) { - var propName; // Reserved names are extracted + function defineRefPropWarningGetter$1(props, displayName) { + var warnAboutAccessingRef = function () { + { + if (!specialPropRefWarningShown$1) { + specialPropRefWarningShown$1 = true; - var props = {}; - var key = null; - var ref = null; - var self = null; - var source = null; + error( + "%s: `ref` is not a prop. Trying to access it will result " + + "in `undefined` being returned. If you need to access the same " + + "value within the child component, you should pass it as a different " + + "prop. (https://reactjs.org/link/special-props)", + displayName + ); + } + } + }; - if (config != null) { - if (hasValidRef$1(config)) { - ref = config.ref; + warnAboutAccessingRef.isReactWarning = true; + Object.defineProperty(props, "ref", { + get: warnAboutAccessingRef, + configurable: true + }); + } + function warnIfStringRefCannotBeAutoConverted$1(config) { { - warnIfStringRefCannotBeAutoConverted$1(config); + if ( + typeof config.ref === "string" && + ReactCurrentOwner$2.current && + config.__self && + ReactCurrentOwner$2.current.stateNode !== config.__self + ) { + var componentName = getComponentNameFromType( + ReactCurrentOwner$2.current.type + ); + + if (!didWarnAboutStringRefs$1[componentName]) { + error( + 'Component "%s" contains the string ref "%s". ' + + "Support for string refs will be removed in a future major release. " + + "This case cannot be automatically converted to an arrow function. " + + "We ask you to manually fix this case by using useRef() or createRef() instead. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-string-ref", + componentName, + config.ref + ); + + didWarnAboutStringRefs$1[componentName] = true; + } + } } } + /** + * Factory method to create a new React element. This no longer adheres to + * the class pattern, so do not use new to call it. Also, instanceof check + * will not work. Instead test $$typeof field against Symbol.for('react.element') to check + * if something is a React Element. + * + * @param {*} type + * @param {*} props + * @param {*} key + * @param {string|object} ref + * @param {*} owner + * @param {*} self A *temporary* helper to detect places where `this` is + * different from the `owner` when React.createElement is called, so that we + * can warn. We want to get rid of owner and replace string `ref`s with arrow + * functions, and as long as `this` and owner are the same, there will be no + * change in behavior. + * @param {*} source An annotation object (added by a transpiler or otherwise) + * indicating filename, line number, and/or other information. + * @internal + */ + + function ReactElement$1(type, key, ref, self, source, owner, props) { + var element = { + // This tag allows us to uniquely identify this as a React Element + $$typeof: REACT_ELEMENT_TYPE, + // Built-in properties that belong on the element + type: type, + key: key, + ref: ref, + props: props, + // Record the component responsible for creating this element. + _owner: owner + }; - if (hasValidKey$1(config)) { { - checkKeyStringCoercion(config.key); + // The validation flag is currently mutative. We put it on + // an external backing store so that we can freeze the whole object. + // This can be replaced with a WeakMap once they are implemented in + // commonly used development environments. + element._store = {}; // To make comparing ReactElements easier for testing purposes, we make + // the validation flag non-enumerable (where possible, which should + // include every environment we run tests in), so the test framework + // ignores it. + + Object.defineProperty(element._store, "validated", { + configurable: false, + enumerable: false, + writable: true, + value: false + }); // self and source are DEV only properties. + + Object.defineProperty(element, "_self", { + configurable: false, + enumerable: false, + writable: false, + value: self + }); // Two elements created in two different places should be considered + // equal for testing purposes and therefore we hide it from enumeration. + + Object.defineProperty(element, "_source", { + configurable: false, + enumerable: false, + writable: false, + value: source + }); + + if (Object.freeze) { + Object.freeze(element.props); + Object.freeze(element); + } } - key = "" + config.key; + return element; } + /** + * Create and return a new ReactElement of the given type. + * See https://reactjs.org/docs/react-api.html#createelement + */ + + function createElement$1(type, config, children) { + var propName; // Reserved names are extracted + + var props = {}; + var key = null; + var ref = null; + var self = null; + var source = null; + + if (config != null) { + if (hasValidRef$1(config)) { + ref = config.ref; + + { + warnIfStringRefCannotBeAutoConverted$1(config); + } + } - self = config.__self === undefined ? null : config.__self; - source = config.__source === undefined ? null : config.__source; // Remaining properties are added to a new props object + if (hasValidKey$1(config)) { + { + checkKeyStringCoercion(config.key); + } - for (propName in config) { - if ( - hasOwnProperty.call(config, propName) && - !RESERVED_PROPS$1.hasOwnProperty(propName) - ) { - props[propName] = config[propName]; - } - } - } // Children can be more than one argument, and those are transferred onto - // the newly allocated props object. + key = "" + config.key; + } - var childrenLength = arguments.length - 2; + self = config.__self === undefined ? null : config.__self; + source = config.__source === undefined ? null : config.__source; // Remaining properties are added to a new props object - if (childrenLength === 1) { - props.children = children; - } else if (childrenLength > 1) { - var childArray = Array(childrenLength); + for (propName in config) { + if ( + hasOwnProperty.call(config, propName) && + !RESERVED_PROPS$1.hasOwnProperty(propName) + ) { + props[propName] = config[propName]; + } + } + } // Children can be more than one argument, and those are transferred onto + // the newly allocated props object. - for (var i = 0; i < childrenLength; i++) { - childArray[i] = arguments[i + 2]; - } + var childrenLength = arguments.length - 2; - { - if (Object.freeze) { - Object.freeze(childArray); - } - } + if (childrenLength === 1) { + props.children = children; + } else if (childrenLength > 1) { + var childArray = Array(childrenLength); - props.children = childArray; - } // Resolve default props + for (var i = 0; i < childrenLength; i++) { + childArray[i] = arguments[i + 2]; + } - if (type && type.defaultProps) { - var defaultProps = type.defaultProps; + { + if (Object.freeze) { + Object.freeze(childArray); + } + } - for (propName in defaultProps) { - if (props[propName] === undefined) { - props[propName] = defaultProps[propName]; - } - } - } + props.children = childArray; + } // Resolve default props - { - if (key || ref) { - var displayName = - typeof type === "function" - ? type.displayName || type.name || "Unknown" - : type; + if (type && type.defaultProps) { + var defaultProps = type.defaultProps; - if (key) { - defineKeyPropWarningGetter$1(props, displayName); + for (propName in defaultProps) { + if (props[propName] === undefined) { + props[propName] = defaultProps[propName]; + } + } } - if (ref) { - defineRefPropWarningGetter$1(props, displayName); + { + if (key || ref) { + var displayName = + typeof type === "function" + ? type.displayName || type.name || "Unknown" + : type; + + if (key) { + defineKeyPropWarningGetter$1(props, displayName); + } + + if (ref) { + defineRefPropWarningGetter$1(props, displayName); + } + } } + + return ReactElement$1( + type, + key, + ref, + self, + source, + ReactCurrentOwner$2.current, + props + ); } - } + function cloneAndReplaceKey(oldElement, newKey) { + var newElement = ReactElement$1( + oldElement.type, + newKey, + oldElement.ref, + oldElement._self, + oldElement._source, + oldElement._owner, + oldElement.props + ); + return newElement; + } + /** + * Clone and return a new ReactElement using element as the starting point. + * See https://reactjs.org/docs/react-api.html#cloneelement + */ + + function cloneElement$1(element, config, children) { + if (element === null || element === undefined) { + throw new Error( + "React.cloneElement(...): The argument must be a React element, but you passed " + + element + + "." + ); + } - return ReactElement$1( - type, - key, - ref, - self, - source, - ReactCurrentOwner$2.current, - props - ); -} -function cloneAndReplaceKey(oldElement, newKey) { - var newElement = ReactElement$1( - oldElement.type, - newKey, - oldElement.ref, - oldElement._self, - oldElement._source, - oldElement._owner, - oldElement.props - ); - return newElement; -} -/** - * Clone and return a new ReactElement using element as the starting point. - * See https://reactjs.org/docs/react-api.html#cloneelement - */ + var propName; // Original props are copied -function cloneElement$1(element, config, children) { - if (element === null || element === undefined) { - throw new Error( - "React.cloneElement(...): The argument must be a React element, but you passed " + - element + - "." - ); - } + var props = assign({}, element.props); // Reserved names are extracted - var propName; // Original props are copied + var key = element.key; + var ref = element.ref; // Self is preserved since the owner is preserved. - var props = assign({}, element.props); // Reserved names are extracted + var self = element._self; // Source is preserved since cloneElement is unlikely to be targeted by a + // transpiler, and the original source is probably a better indicator of the + // true owner. - var key = element.key; - var ref = element.ref; // Self is preserved since the owner is preserved. + var source = element._source; // Owner will be preserved, unless ref is overridden - var self = element._self; // Source is preserved since cloneElement is unlikely to be targeted by a - // transpiler, and the original source is probably a better indicator of the - // true owner. + var owner = element._owner; - var source = element._source; // Owner will be preserved, unless ref is overridden + if (config != null) { + if (hasValidRef$1(config)) { + // Silently steal the ref from the parent. + ref = config.ref; + owner = ReactCurrentOwner$2.current; + } - var owner = element._owner; + if (hasValidKey$1(config)) { + { + checkKeyStringCoercion(config.key); + } - if (config != null) { - if (hasValidRef$1(config)) { - // Silently steal the ref from the parent. - ref = config.ref; - owner = ReactCurrentOwner$2.current; - } + key = "" + config.key; + } // Remaining properties override existing props - if (hasValidKey$1(config)) { - { - checkKeyStringCoercion(config.key); - } + var defaultProps; + + if (element.type && element.type.defaultProps) { + defaultProps = element.type.defaultProps; + } - key = "" + config.key; - } // Remaining properties override existing props + for (propName in config) { + if ( + hasOwnProperty.call(config, propName) && + !RESERVED_PROPS$1.hasOwnProperty(propName) + ) { + if (config[propName] === undefined && defaultProps !== undefined) { + // Resolve default props + props[propName] = defaultProps[propName]; + } else { + props[propName] = config[propName]; + } + } + } + } // Children can be more than one argument, and those are transferred onto + // the newly allocated props object. - var defaultProps; + var childrenLength = arguments.length - 2; - if (element.type && element.type.defaultProps) { - defaultProps = element.type.defaultProps; - } + if (childrenLength === 1) { + props.children = children; + } else if (childrenLength > 1) { + var childArray = Array(childrenLength); - for (propName in config) { - if ( - hasOwnProperty.call(config, propName) && - !RESERVED_PROPS$1.hasOwnProperty(propName) - ) { - if (config[propName] === undefined && defaultProps !== undefined) { - // Resolve default props - props[propName] = defaultProps[propName]; - } else { - props[propName] = config[propName]; + for (var i = 0; i < childrenLength; i++) { + childArray[i] = arguments[i + 2]; } + + props.children = childArray; } + + return ReactElement$1(element.type, key, ref, self, source, owner, props); + } + /** + * Verifies the object is a ReactElement. + * See https://reactjs.org/docs/react-api.html#isvalidelement + * @param {?object} object + * @return {boolean} True if `object` is a ReactElement. + * @final + */ + + function isValidElement$1(object) { + return ( + typeof object === "object" && + object !== null && + object.$$typeof === REACT_ELEMENT_TYPE + ); } - } // Children can be more than one argument, and those are transferred onto - // the newly allocated props object. - var childrenLength = arguments.length - 2; + var SEPARATOR = "."; + var SUBSEPARATOR = ":"; + /** + * Escape and wrap key so it is safe to use as a reactid + * + * @param {string} key to be escaped. + * @return {string} the escaped key. + */ + + function escape(key) { + var escapeRegex = /[=:]/g; + var escaperLookup = { + "=": "=0", + ":": "=2" + }; + var escapedString = key.replace(escapeRegex, function (match) { + return escaperLookup[match]; + }); + return "$" + escapedString; + } + /** + * TODO: Test that a single child and an array with one item have the same key + * pattern. + */ - if (childrenLength === 1) { - props.children = children; - } else if (childrenLength > 1) { - var childArray = Array(childrenLength); + var didWarnAboutMaps = false; + var userProvidedKeyEscapeRegex = /\/+/g; - for (var i = 0; i < childrenLength; i++) { - childArray[i] = arguments[i + 2]; + function escapeUserProvidedKey(text) { + return text.replace(userProvidedKeyEscapeRegex, "$&/"); } + /** + * Generate a key string that identifies a element within a set. + * + * @param {*} element A element that could contain a manual key. + * @param {number} index Index that is used if a manual key is not provided. + * @return {string} + */ + + function getElementKey(element, index) { + // Do some typechecking here since we call this blindly. We want to ensure + // that we don't block potential future ES APIs. + if ( + typeof element === "object" && + element !== null && + element.key != null + ) { + // Explicit key + { + checkKeyStringCoercion(element.key); + } - props.children = childArray; - } + return escape("" + element.key); + } // Implicit key determined by the index in the set - return ReactElement$1(element.type, key, ref, self, source, owner, props); -} -/** - * Verifies the object is a ReactElement. - * See https://reactjs.org/docs/react-api.html#isvalidelement - * @param {?object} object - * @return {boolean} True if `object` is a ReactElement. - * @final - */ + return index.toString(36); + } -function isValidElement$1(object) { - return ( - typeof object === "object" && - object !== null && - object.$$typeof === REACT_ELEMENT_TYPE - ); -} + function mapIntoArray(children, array, escapedPrefix, nameSoFar, callback) { + var type = typeof children; -var SEPARATOR = "."; -var SUBSEPARATOR = ":"; -/** - * Escape and wrap key so it is safe to use as a reactid - * - * @param {string} key to be escaped. - * @return {string} the escaped key. - */ + if (type === "undefined" || type === "boolean") { + // All of the above are perceived as null. + children = null; + } -function escape(key) { - var escapeRegex = /[=:]/g; - var escaperLookup = { - "=": "=0", - ":": "=2" - }; - var escapedString = key.replace(escapeRegex, function (match) { - return escaperLookup[match]; - }); - return "$" + escapedString; -} -/** - * TODO: Test that a single child and an array with one item have the same key - * pattern. - */ + var invokeCallback = false; -var didWarnAboutMaps = false; -var userProvidedKeyEscapeRegex = /\/+/g; + if (children === null) { + invokeCallback = true; + } else { + switch (type) { + case "string": + case "number": + invokeCallback = true; + break; -function escapeUserProvidedKey(text) { - return text.replace(userProvidedKeyEscapeRegex, "$&/"); -} -/** - * Generate a key string that identifies a element within a set. - * - * @param {*} element A element that could contain a manual key. - * @param {number} index Index that is used if a manual key is not provided. - * @return {string} - */ + case "object": + switch (children.$$typeof) { + case REACT_ELEMENT_TYPE: + case REACT_PORTAL_TYPE: + invokeCallback = true; + } + } + } -function getElementKey(element, index) { - // Do some typechecking here since we call this blindly. We want to ensure - // that we don't block potential future ES APIs. - if (typeof element === "object" && element !== null && element.key != null) { - // Explicit key - { - checkKeyStringCoercion(element.key); - } + if (invokeCallback) { + var _child = children; + var mappedChild = callback(_child); // If it's the only child, treat the name as if it was wrapped in an array + // so that it's consistent if the number of children grows: - return escape("" + element.key); - } // Implicit key determined by the index in the set + var childKey = + nameSoFar === "" ? SEPARATOR + getElementKey(_child, 0) : nameSoFar; - return index.toString(36); -} + if (isArray(mappedChild)) { + var escapedChildKey = ""; -function mapIntoArray(children, array, escapedPrefix, nameSoFar, callback) { - var type = typeof children; + if (childKey != null) { + escapedChildKey = escapeUserProvidedKey(childKey) + "/"; + } - if (type === "undefined" || type === "boolean") { - // All of the above are perceived as null. - children = null; - } + mapIntoArray(mappedChild, array, escapedChildKey, "", function (c) { + return c; + }); + } else if (mappedChild != null) { + if (isValidElement$1(mappedChild)) { + { + // The `if` statement here prevents auto-disabling of the safe + // coercion ESLint rule, so we must manually disable it below. + // $FlowFixMe[incompatible-type] Flow incorrectly thinks React.Portal doesn't have a key + if ( + mappedChild.key && + (!_child || _child.key !== mappedChild.key) + ) { + checkKeyStringCoercion(mappedChild.key); + } + } - var invokeCallback = false; + mappedChild = cloneAndReplaceKey( + mappedChild, // Keep both the (mapped) and old keys if they differ, just as + // traverseAllChildren used to do for objects as children + escapedPrefix + // $FlowFixMe[incompatible-type] Flow incorrectly thinks React.Portal doesn't have a key + (mappedChild.key && (!_child || _child.key !== mappedChild.key) + ? escapeUserProvidedKey( + // $FlowFixMe[unsafe-addition] + "" + mappedChild.key // eslint-disable-line react-internal/safe-string-coercion + ) + "/" + : "") + + childKey + ); + } - if (children === null) { - invokeCallback = true; - } else { - switch (type) { - case "string": - case "number": - invokeCallback = true; - break; + array.push(mappedChild); + } - case "object": - switch (children.$$typeof) { - case REACT_ELEMENT_TYPE: - case REACT_PORTAL_TYPE: - invokeCallback = true; + return 1; + } + + var child; + var nextName; + var subtreeCount = 0; // Count of children found in the current subtree. + + var nextNamePrefix = + nameSoFar === "" ? SEPARATOR : nameSoFar + SUBSEPARATOR; + + if (isArray(children)) { + for (var i = 0; i < children.length; i++) { + child = children[i]; + nextName = nextNamePrefix + getElementKey(child, i); + subtreeCount += mapIntoArray( + child, + array, + escapedPrefix, + nextName, + callback + ); } - } - } + } else { + var iteratorFn = getIteratorFn(children); + + if (typeof iteratorFn === "function") { + var iterableChildren = children; + + { + // Warn about using Maps as children + if (iteratorFn === iterableChildren.entries) { + if (!didWarnAboutMaps) { + warn( + "Using Maps as children is not supported. " + + "Use an array of keyed ReactElements instead." + ); + } - if (invokeCallback) { - var _child = children; - var mappedChild = callback(_child); // If it's the only child, treat the name as if it was wrapped in an array - // so that it's consistent if the number of children grows: + didWarnAboutMaps = true; + } + } - var childKey = - nameSoFar === "" ? SEPARATOR + getElementKey(_child, 0) : nameSoFar; + var iterator = iteratorFn.call(iterableChildren); + var step; + var ii = 0; // $FlowFixMe[incompatible-use] `iteratorFn` might return null according to typing. - if (isArray(mappedChild)) { - var escapedChildKey = ""; + while (!(step = iterator.next()).done) { + child = step.value; + nextName = nextNamePrefix + getElementKey(child, ii++); + subtreeCount += mapIntoArray( + child, + array, + escapedPrefix, + nextName, + callback + ); + } + } else if (type === "object") { + // eslint-disable-next-line react-internal/safe-string-coercion + var childrenString = String(children); + throw new Error( + "Objects are not valid as a React child (found: " + + (childrenString === "[object Object]" + ? "object with keys {" + Object.keys(children).join(", ") + "}" + : childrenString) + + "). " + + "If you meant to render a collection of children, use an array " + + "instead." + ); + } + } - if (childKey != null) { - escapedChildKey = escapeUserProvidedKey(childKey) + "/"; + return subtreeCount; + } + /** + * Maps children that are typically specified as `props.children`. + * + * See https://reactjs.org/docs/react-api.html#reactchildrenmap + * + * The provided mapFunction(child, index) will be called for each + * leaf child. + * + * @param {?*} children Children tree container. + * @param {function(*, int)} func The map function. + * @param {*} context Context for mapFunction. + * @return {object} Object containing the ordered map of results. + */ + + function mapChildren(children, func, context) { + if (children == null) { + return children; } - mapIntoArray(mappedChild, array, escapedChildKey, "", function (c) { - return c; + var result = []; + var count = 0; + mapIntoArray(children, result, "", "", function (child) { + return func.call(context, child, count++); }); - } else if (mappedChild != null) { - if (isValidElement$1(mappedChild)) { - { - // The `if` statement here prevents auto-disabling of the safe - // coercion ESLint rule, so we must manually disable it below. - // $FlowFixMe[incompatible-type] Flow incorrectly thinks React.Portal doesn't have a key - if (mappedChild.key && (!_child || _child.key !== mappedChild.key)) { - checkKeyStringCoercion(mappedChild.key); - } - } - - mappedChild = cloneAndReplaceKey( - mappedChild, // Keep both the (mapped) and old keys if they differ, just as - // traverseAllChildren used to do for objects as children - escapedPrefix + // $FlowFixMe[incompatible-type] Flow incorrectly thinks React.Portal doesn't have a key - (mappedChild.key && (!_child || _child.key !== mappedChild.key) - ? escapeUserProvidedKey( - // $FlowFixMe[unsafe-addition] - "" + mappedChild.key // eslint-disable-line react-internal/safe-string-coercion - ) + "/" - : "") + - childKey + return result; + } + /** + * Count the number of children that are typically specified as + * `props.children`. + * + * See https://reactjs.org/docs/react-api.html#reactchildrencount + * + * @param {?*} children Children tree container. + * @return {number} The number of children. + */ + + function countChildren(children) { + var n = 0; + mapChildren(children, function () { + n++; // Don't return anything + }); + return n; + } + /** + * Iterates through children that are typically specified as `props.children`. + * + * See https://reactjs.org/docs/react-api.html#reactchildrenforeach + * + * The provided forEachFunc(child, index) will be called for each + * leaf child. + * + * @param {?*} children Children tree container. + * @param {function(*, int)} forEachFunc + * @param {*} forEachContext Context for forEachContext. + */ + + function forEachChildren(children, forEachFunc, forEachContext) { + mapChildren( + children, // $FlowFixMe[missing-this-annot] + function () { + forEachFunc.apply(this, arguments); // Don't return anything. + }, + forEachContext + ); + } + /** + * Flatten a children object (typically specified as `props.children`) and + * return an array with appropriately re-keyed children. + * + * See https://reactjs.org/docs/react-api.html#reactchildrentoarray + */ + + function toArray(children) { + return ( + mapChildren(children, function (child) { + return child; + }) || [] + ); + } + /** + * Returns the first child in a collection of children and verifies that there + * is only one child in the collection. + * + * See https://reactjs.org/docs/react-api.html#reactchildrenonly + * + * The current implementation of this function assumes that a single child gets + * passed without a wrapper, but the purpose of this helper function is to + * abstract away the particular structure of children. + * + * @param {?object} children Child collection structure. + * @return {ReactElement} The first and only `ReactElement` contained in the + * structure. + */ + + function onlyChild(children) { + if (!isValidElement$1(children)) { + throw new Error( + "React.Children.only expected to receive a single React element child." ); } - array.push(mappedChild); + return children; } - return 1; - } - - var child; - var nextName; - var subtreeCount = 0; // Count of children found in the current subtree. - - var nextNamePrefix = nameSoFar === "" ? SEPARATOR : nameSoFar + SUBSEPARATOR; + function createContext(defaultValue) { + // TODO: Second argument used to be an optional `calculateChangedBits` + // function. Warn to reserve for future use? + var context = { + $$typeof: REACT_CONTEXT_TYPE, + // As a workaround to support multiple concurrent renderers, we categorize + // some renderers as primary and others as secondary. We only expect + // there to be two concurrent renderers at most: React Native (primary) and + // Fabric (secondary); React DOM (primary) and React ART (secondary). + // Secondary renderers store their context values on separate fields. + _currentValue: defaultValue, + _currentValue2: defaultValue, + // Used to track how many concurrent renderers this context currently + // supports within in a single renderer. Such as parallel server rendering. + _threadCount: 0, + // These are circular + Provider: null, + Consumer: null, + // Add these to use same hidden class in VM as ServerContext + _defaultValue: null, + _globalName: null + }; + context.Provider = { + $$typeof: REACT_PROVIDER_TYPE, + _context: context + }; + var hasWarnedAboutUsingNestedContextConsumers = false; + var hasWarnedAboutUsingConsumerProvider = false; + var hasWarnedAboutDisplayNameOnConsumer = false; - if (isArray(children)) { - for (var i = 0; i < children.length; i++) { - child = children[i]; - nextName = nextNamePrefix + getElementKey(child, i); - subtreeCount += mapIntoArray( - child, - array, - escapedPrefix, - nextName, - callback - ); - } - } else { - var iteratorFn = getIteratorFn(children); + { + // A separate object, but proxies back to the original context object for + // backwards compatibility. It has a different $$typeof, so we can properly + // warn for the incorrect usage of Context as a Consumer. + var Consumer = { + $$typeof: REACT_CONTEXT_TYPE, + _context: context + }; // $FlowFixMe[prop-missing]: Flow complains about not setting a value, which is intentional here + + Object.defineProperties(Consumer, { + Provider: { + get: function () { + if (!hasWarnedAboutUsingConsumerProvider) { + hasWarnedAboutUsingConsumerProvider = true; + + error( + "Rendering is not supported and will be removed in " + + "a future major release. Did you mean to render instead?" + ); + } - if (typeof iteratorFn === "function") { - var iterableChildren = children; + return context.Provider; + }, + set: function (_Provider) { + context.Provider = _Provider; + } + }, + _currentValue: { + get: function () { + return context._currentValue; + }, + set: function (_currentValue) { + context._currentValue = _currentValue; + } + }, + _currentValue2: { + get: function () { + return context._currentValue2; + }, + set: function (_currentValue2) { + context._currentValue2 = _currentValue2; + } + }, + _threadCount: { + get: function () { + return context._threadCount; + }, + set: function (_threadCount) { + context._threadCount = _threadCount; + } + }, + Consumer: { + get: function () { + if (!hasWarnedAboutUsingNestedContextConsumers) { + hasWarnedAboutUsingNestedContextConsumers = true; + + error( + "Rendering is not supported and will be removed in " + + "a future major release. Did you mean to render instead?" + ); + } - { - // Warn about using Maps as children - if (iteratorFn === iterableChildren.entries) { - if (!didWarnAboutMaps) { - warn( - "Using Maps as children is not supported. " + - "Use an array of keyed ReactElements instead." - ); + return context.Consumer; + } + }, + displayName: { + get: function () { + return context.displayName; + }, + set: function (displayName) { + if (!hasWarnedAboutDisplayNameOnConsumer) { + warn( + "Setting `displayName` on Context.Consumer has no effect. " + + "You should set it directly on the context with Context.displayName = '%s'.", + displayName + ); + + hasWarnedAboutDisplayNameOnConsumer = true; + } + } } + }); // $FlowFixMe[prop-missing]: Flow complains about missing properties because it doesn't understand defineProperty - didWarnAboutMaps = true; - } + context.Consumer = Consumer; } - var iterator = iteratorFn.call(iterableChildren); - var step; - var ii = 0; // $FlowFixMe[incompatible-use] `iteratorFn` might return null according to typing. - - while (!(step = iterator.next()).done) { - child = step.value; - nextName = nextNamePrefix + getElementKey(child, ii++); - subtreeCount += mapIntoArray( - child, - array, - escapedPrefix, - nextName, - callback - ); + { + context._currentRenderer = null; + context._currentRenderer2 = null; } - } else if (type === "object") { - // eslint-disable-next-line react-internal/safe-string-coercion - var childrenString = String(children); - throw new Error( - "Objects are not valid as a React child (found: " + - (childrenString === "[object Object]" - ? "object with keys {" + Object.keys(children).join(", ") + "}" - : childrenString) + - "). " + - "If you meant to render a collection of children, use an array " + - "instead." - ); - } - } - - return subtreeCount; -} -/** - * Maps children that are typically specified as `props.children`. - * - * See https://reactjs.org/docs/react-api.html#reactchildrenmap - * - * The provided mapFunction(child, index) will be called for each - * leaf child. - * - * @param {?*} children Children tree container. - * @param {function(*, int)} func The map function. - * @param {*} context Context for mapFunction. - * @return {object} Object containing the ordered map of results. - */ - -function mapChildren(children, func, context) { - if (children == null) { - return children; - } - - var result = []; - var count = 0; - mapIntoArray(children, result, "", "", function (child) { - return func.call(context, child, count++); - }); - return result; -} -/** - * Count the number of children that are typically specified as - * `props.children`. - * - * See https://reactjs.org/docs/react-api.html#reactchildrencount - * - * @param {?*} children Children tree container. - * @return {number} The number of children. - */ - -function countChildren(children) { - var n = 0; - mapChildren(children, function () { - n++; // Don't return anything - }); - return n; -} -/** - * Iterates through children that are typically specified as `props.children`. - * - * See https://reactjs.org/docs/react-api.html#reactchildrenforeach - * - * The provided forEachFunc(child, index) will be called for each - * leaf child. - * - * @param {?*} children Children tree container. - * @param {function(*, int)} forEachFunc - * @param {*} forEachContext Context for forEachContext. - */ - -function forEachChildren(children, forEachFunc, forEachContext) { - mapChildren( - children, // $FlowFixMe[missing-this-annot] - function () { - forEachFunc.apply(this, arguments); // Don't return anything. - }, - forEachContext - ); -} -/** - * Flatten a children object (typically specified as `props.children`) and - * return an array with appropriately re-keyed children. - * - * See https://reactjs.org/docs/react-api.html#reactchildrentoarray - */ -function toArray(children) { - return ( - mapChildren(children, function (child) { - return child; - }) || [] - ); -} -/** - * Returns the first child in a collection of children and verifies that there - * is only one child in the collection. - * - * See https://reactjs.org/docs/react-api.html#reactchildrenonly - * - * The current implementation of this function assumes that a single child gets - * passed without a wrapper, but the purpose of this helper function is to - * abstract away the particular structure of children. - * - * @param {?object} children Child collection structure. - * @return {ReactElement} The first and only `ReactElement` contained in the - * structure. - */ + return context; + } -function onlyChild(children) { - if (!isValidElement$1(children)) { - throw new Error( - "React.Children.only expected to receive a single React element child." - ); - } + var Uninitialized = -1; + var Pending = 0; + var Resolved = 1; + var Rejected = 2; + + function lazyInitializer(payload) { + if (payload._status === Uninitialized) { + var ctor = payload._result; + var thenable = ctor(); // Transition to the next state. + // This might throw either because it's missing or throws. If so, we treat it + // as still uninitialized and try again next time. Which is the same as what + // happens if the ctor or any wrappers processing the ctor throws. This might + // end up fixing it if the resolution was a concurrency bug. + + thenable.then( + function (moduleObject) { + if ( + payload._status === Pending || + payload._status === Uninitialized + ) { + // Transition to the next state. + var resolved = payload; + resolved._status = Resolved; + resolved._result = moduleObject; + } + }, + function (error) { + if ( + payload._status === Pending || + payload._status === Uninitialized + ) { + // Transition to the next state. + var rejected = payload; + rejected._status = Rejected; + rejected._result = error; + } + } + ); - return children; -} + if (payload._status === Uninitialized) { + // In case, we're still uninitialized, then we're waiting for the thenable + // to resolve. Set it as pending in the meantime. + var pending = payload; + pending._status = Pending; + pending._result = thenable; + } + } -function createContext(defaultValue) { - // TODO: Second argument used to be an optional `calculateChangedBits` - // function. Warn to reserve for future use? - var context = { - $$typeof: REACT_CONTEXT_TYPE, - // As a workaround to support multiple concurrent renderers, we categorize - // some renderers as primary and others as secondary. We only expect - // there to be two concurrent renderers at most: React Native (primary) and - // Fabric (secondary); React DOM (primary) and React ART (secondary). - // Secondary renderers store their context values on separate fields. - _currentValue: defaultValue, - _currentValue2: defaultValue, - // Used to track how many concurrent renderers this context currently - // supports within in a single renderer. Such as parallel server rendering. - _threadCount: 0, - // These are circular - Provider: null, - Consumer: null, - // Add these to use same hidden class in VM as ServerContext - _defaultValue: null, - _globalName: null - }; - context.Provider = { - $$typeof: REACT_PROVIDER_TYPE, - _context: context - }; - var hasWarnedAboutUsingNestedContextConsumers = false; - var hasWarnedAboutUsingConsumerProvider = false; - var hasWarnedAboutDisplayNameOnConsumer = false; - - { - // A separate object, but proxies back to the original context object for - // backwards compatibility. It has a different $$typeof, so we can properly - // warn for the incorrect usage of Context as a Consumer. - var Consumer = { - $$typeof: REACT_CONTEXT_TYPE, - _context: context - }; // $FlowFixMe[prop-missing]: Flow complains about not setting a value, which is intentional here - - Object.defineProperties(Consumer, { - Provider: { - get: function () { - if (!hasWarnedAboutUsingConsumerProvider) { - hasWarnedAboutUsingConsumerProvider = true; + if (payload._status === Resolved) { + var moduleObject = payload._result; + { + if (moduleObject === undefined) { error( - "Rendering is not supported and will be removed in " + - "a future major release. Did you mean to render instead?" + "lazy: Expected the result of a dynamic imp" + + "ort() call. " + + "Instead received: %s\n\nYour code should look like: \n " + // Break up imports to avoid accidentally parsing them as dependencies. + "const MyComponent = lazy(() => imp" + + "ort('./MyComponent'))\n\n" + + "Did you accidentally put curly braces around the import?", + moduleObject ); } - - return context.Provider; - }, - set: function (_Provider) { - context.Provider = _Provider; } - }, - _currentValue: { - get: function () { - return context._currentValue; - }, - set: function (_currentValue) { - context._currentValue = _currentValue; - } - }, - _currentValue2: { - get: function () { - return context._currentValue2; - }, - set: function (_currentValue2) { - context._currentValue2 = _currentValue2; - } - }, - _threadCount: { - get: function () { - return context._threadCount; - }, - set: function (_threadCount) { - context._threadCount = _threadCount; - } - }, - Consumer: { - get: function () { - if (!hasWarnedAboutUsingNestedContextConsumers) { - hasWarnedAboutUsingNestedContextConsumers = true; + { + if (!("default" in moduleObject)) { error( - "Rendering is not supported and will be removed in " + - "a future major release. Did you mean to render instead?" + "lazy: Expected the result of a dynamic imp" + + "ort() call. " + + "Instead received: %s\n\nYour code should look like: \n " + // Break up imports to avoid accidentally parsing them as dependencies. + "const MyComponent = lazy(() => imp" + + "ort('./MyComponent'))", + moduleObject ); } - - return context.Consumer; } - }, - displayName: { - get: function () { - return context.displayName; - }, - set: function (displayName) { - if (!hasWarnedAboutDisplayNameOnConsumer) { - warn( - "Setting `displayName` on Context.Consumer has no effect. " + - "You should set it directly on the context with Context.displayName = '%s'.", - displayName - ); - hasWarnedAboutDisplayNameOnConsumer = true; - } - } + return moduleObject.default; + } else { + throw payload._result; } - }); // $FlowFixMe[prop-missing]: Flow complains about missing properties because it doesn't understand defineProperty - - context.Consumer = Consumer; - } + } - { - context._currentRenderer = null; - context._currentRenderer2 = null; - } + function lazy(ctor) { + var payload = { + // We use these fields to store the result. + _status: Uninitialized, + _result: ctor + }; + var lazyType = { + $$typeof: REACT_LAZY_TYPE, + _payload: payload, + _init: lazyInitializer + }; - return context; -} + { + // In production, this would just set it on the object. + var defaultProps; + var propTypes; // $FlowFixMe[prop-missing] + + Object.defineProperties(lazyType, { + defaultProps: { + configurable: true, + get: function () { + return defaultProps; + }, + // $FlowFixMe[missing-local-annot] + set: function (newDefaultProps) { + error( + "React.lazy(...): It is not supported to assign `defaultProps` to " + + "a lazy component import. Either specify them where the component " + + "is defined, or create a wrapping component around it." + ); -var Uninitialized = -1; -var Pending = 0; -var Resolved = 1; -var Rejected = 2; - -function lazyInitializer(payload) { - if (payload._status === Uninitialized) { - var ctor = payload._result; - var thenable = ctor(); // Transition to the next state. - // This might throw either because it's missing or throws. If so, we treat it - // as still uninitialized and try again next time. Which is the same as what - // happens if the ctor or any wrappers processing the ctor throws. This might - // end up fixing it if the resolution was a concurrency bug. - - thenable.then( - function (moduleObject) { - if (payload._status === Pending || payload._status === Uninitialized) { - // Transition to the next state. - var resolved = payload; - resolved._status = Resolved; - resolved._result = moduleObject; - } - }, - function (error) { - if (payload._status === Pending || payload._status === Uninitialized) { - // Transition to the next state. - var rejected = payload; - rejected._status = Rejected; - rejected._result = error; - } - } - ); + defaultProps = newDefaultProps; // Match production behavior more closely: + // $FlowFixMe[prop-missing] - if (payload._status === Uninitialized) { - // In case, we're still uninitialized, then we're waiting for the thenable - // to resolve. Set it as pending in the meantime. - var pending = payload; - pending._status = Pending; - pending._result = thenable; - } - } + Object.defineProperty(lazyType, "defaultProps", { + enumerable: true + }); + } + }, + propTypes: { + configurable: true, + get: function () { + return propTypes; + }, + // $FlowFixMe[missing-local-annot] + set: function (newPropTypes) { + error( + "React.lazy(...): It is not supported to assign `propTypes` to " + + "a lazy component import. Either specify them where the component " + + "is defined, or create a wrapping component around it." + ); - if (payload._status === Resolved) { - var moduleObject = payload._result; + propTypes = newPropTypes; // Match production behavior more closely: + // $FlowFixMe[prop-missing] - { - if (moduleObject === undefined) { - error( - "lazy: Expected the result of a dynamic imp" + - "ort() call. " + - "Instead received: %s\n\nYour code should look like: \n " + // Break up imports to avoid accidentally parsing them as dependencies. - "const MyComponent = lazy(() => imp" + - "ort('./MyComponent'))\n\n" + - "Did you accidentally put curly braces around the import?", - moduleObject - ); + Object.defineProperty(lazyType, "propTypes", { + enumerable: true + }); + } + } + }); } - } - { - if (!("default" in moduleObject)) { - error( - "lazy: Expected the result of a dynamic imp" + - "ort() call. " + - "Instead received: %s\n\nYour code should look like: \n " + // Break up imports to avoid accidentally parsing them as dependencies. - "const MyComponent = lazy(() => imp" + - "ort('./MyComponent'))", - moduleObject - ); - } + return lazyType; } - return moduleObject.default; - } else { - throw payload._result; - } -} - -function lazy(ctor) { - var payload = { - // We use these fields to store the result. - _status: Uninitialized, - _result: ctor - }; - var lazyType = { - $$typeof: REACT_LAZY_TYPE, - _payload: payload, - _init: lazyInitializer - }; - - { - // In production, this would just set it on the object. - var defaultProps; - var propTypes; // $FlowFixMe[prop-missing] - - Object.defineProperties(lazyType, { - defaultProps: { - configurable: true, - get: function () { - return defaultProps; - }, - // $FlowFixMe[missing-local-annot] - set: function (newDefaultProps) { + function forwardRef(render) { + { + if (render != null && render.$$typeof === REACT_MEMO_TYPE) { error( - "React.lazy(...): It is not supported to assign `defaultProps` to " + - "a lazy component import. Either specify them where the component " + - "is defined, or create a wrapping component around it." + "forwardRef requires a render function but received a `memo` " + + "component. Instead of forwardRef(memo(...)), use " + + "memo(forwardRef(...))." ); - - defaultProps = newDefaultProps; // Match production behavior more closely: - // $FlowFixMe[prop-missing] - - Object.defineProperty(lazyType, "defaultProps", { - enumerable: true - }); - } - }, - propTypes: { - configurable: true, - get: function () { - return propTypes; - }, - // $FlowFixMe[missing-local-annot] - set: function (newPropTypes) { + } else if (typeof render !== "function") { error( - "React.lazy(...): It is not supported to assign `propTypes` to " + - "a lazy component import. Either specify them where the component " + - "is defined, or create a wrapping component around it." + "forwardRef requires a render function but was given %s.", + render === null ? "null" : typeof render ); + } else { + if (render.length !== 0 && render.length !== 2) { + error( + "forwardRef render functions accept exactly two parameters: props and ref. %s", + render.length === 1 + ? "Did you forget to use the ref parameter?" + : "Any additional parameter will be undefined." + ); + } + } - propTypes = newPropTypes; // Match production behavior more closely: - // $FlowFixMe[prop-missing] - - Object.defineProperty(lazyType, "propTypes", { - enumerable: true - }); + if (render != null) { + if (render.defaultProps != null || render.propTypes != null) { + error( + "forwardRef render functions do not support propTypes or defaultProps. " + + "Did you accidentally pass a React component?" + ); + } } } - }); - } - return lazyType; -} + var elementType = { + $$typeof: REACT_FORWARD_REF_TYPE, + render: render + }; -function forwardRef(render) { - { - if (render != null && render.$$typeof === REACT_MEMO_TYPE) { - error( - "forwardRef requires a render function but received a `memo` " + - "component. Instead of forwardRef(memo(...)), use " + - "memo(forwardRef(...))." - ); - } else if (typeof render !== "function") { - error( - "forwardRef requires a render function but was given %s.", - render === null ? "null" : typeof render - ); - } else { - if (render.length !== 0 && render.length !== 2) { - error( - "forwardRef render functions accept exactly two parameters: props and ref. %s", - render.length === 1 - ? "Did you forget to use the ref parameter?" - : "Any additional parameter will be undefined." - ); + { + var ownName; + Object.defineProperty(elementType, "displayName", { + enumerable: false, + configurable: true, + get: function () { + return ownName; + }, + set: function (name) { + ownName = name; // The inner component shouldn't inherit this display name in most cases, + // because the component may be used elsewhere. + // But it's nice for anonymous functions to inherit the name, + // so that our component-stack generation logic will display their frames. + // An anonymous function generally suggests a pattern like: + // React.forwardRef((props, ref) => {...}); + // This kind of inner function is not used elsewhere so the side effect is okay. + + if (!render.name && !render.displayName) { + render.displayName = name; + } + } + }); } + + return elementType; } - if (render != null) { - if (render.defaultProps != null || render.propTypes != null) { - error( - "forwardRef render functions do not support propTypes or defaultProps. " + - "Did you accidentally pass a React component?" - ); + var REACT_CLIENT_REFERENCE$2 = Symbol.for("react.client.reference"); + function isValidElementType(type) { + if (typeof type === "string" || typeof type === "function") { + return true; + } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill). + + if ( + type === REACT_FRAGMENT_TYPE || + type === REACT_PROFILER_TYPE || + (enableDebugTracing && type === REACT_DEBUG_TRACING_MODE_TYPE) || + type === REACT_STRICT_MODE_TYPE || + type === REACT_SUSPENSE_TYPE || + type === REACT_SUSPENSE_LIST_TYPE || + type === REACT_LEGACY_HIDDEN_TYPE || + type === REACT_OFFSCREEN_TYPE || + type === REACT_SCOPE_TYPE || + type === REACT_CACHE_TYPE || + (enableTransitionTracing && type === REACT_TRACING_MARKER_TYPE) + ) { + return true; } - } - } - var elementType = { - $$typeof: REACT_FORWARD_REF_TYPE, - render: render - }; + if (typeof type === "object" && type !== null) { + if ( + type.$$typeof === REACT_LAZY_TYPE || + type.$$typeof === REACT_MEMO_TYPE || + type.$$typeof === REACT_PROVIDER_TYPE || + type.$$typeof === REACT_CONTEXT_TYPE || + type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object + // types supported by any Flight configuration anywhere since + // we don't know which Flight build this will end up being used + // with. + type.$$typeof === REACT_CLIENT_REFERENCE$2 || + type.getModuleId !== undefined + ) { + return true; + } + } - { - var ownName; - Object.defineProperty(elementType, "displayName", { - enumerable: false, - configurable: true, - get: function () { - return ownName; - }, - set: function (name) { - ownName = name; // The inner component shouldn't inherit this display name in most cases, - // because the component may be used elsewhere. - // But it's nice for anonymous functions to inherit the name, - // so that our component-stack generation logic will display their frames. - // An anonymous function generally suggests a pattern like: - // React.forwardRef((props, ref) => {...}); - // This kind of inner function is not used elsewhere so the side effect is okay. + return false; + } - if (!render.name && !render.displayName) { - render.displayName = name; + function memo(type, compare) { + { + if (!isValidElementType(type)) { + error( + "memo: The first argument must be a component. Instead " + + "received: %s", + type === null ? "null" : typeof type + ); } } - }); - } - return elementType; -} + var elementType = { + $$typeof: REACT_MEMO_TYPE, + type: type, + compare: compare === undefined ? null : compare + }; -var REACT_CLIENT_REFERENCE$2 = Symbol.for("react.client.reference"); -function isValidElementType(type) { - if (typeof type === "string" || typeof type === "function") { - return true; - } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill). - - if ( - type === REACT_FRAGMENT_TYPE || - type === REACT_PROFILER_TYPE || - (enableDebugTracing && type === REACT_DEBUG_TRACING_MODE_TYPE) || - type === REACT_STRICT_MODE_TYPE || - type === REACT_SUSPENSE_TYPE || - type === REACT_SUSPENSE_LIST_TYPE || - type === REACT_LEGACY_HIDDEN_TYPE || - type === REACT_OFFSCREEN_TYPE || - type === REACT_SCOPE_TYPE || - type === REACT_CACHE_TYPE || - (enableTransitionTracing && type === REACT_TRACING_MARKER_TYPE) - ) { - return true; - } - - if (typeof type === "object" && type !== null) { - if ( - type.$$typeof === REACT_LAZY_TYPE || - type.$$typeof === REACT_MEMO_TYPE || - type.$$typeof === REACT_PROVIDER_TYPE || - type.$$typeof === REACT_CONTEXT_TYPE || - type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object - // types supported by any Flight configuration anywhere since - // we don't know which Flight build this will end up being used - // with. - type.$$typeof === REACT_CLIENT_REFERENCE$2 || - type.getModuleId !== undefined - ) { - return true; + { + var ownName; + Object.defineProperty(elementType, "displayName", { + enumerable: false, + configurable: true, + get: function () { + return ownName; + }, + set: function (name) { + ownName = name; // The inner component shouldn't inherit this display name in most cases, + // because the component may be used elsewhere. + // But it's nice for anonymous functions to inherit the name, + // so that our component-stack generation logic will display their frames. + // An anonymous function generally suggests a pattern like: + // React.memo((props) => {...}); + // This kind of inner function is not used elsewhere so the side effect is okay. + + if (!type.name && !type.displayName) { + type.displayName = name; + } + } + }); + } + + return elementType; } - } - return false; -} + /** + * Keeps track of the current Cache dispatcher. + */ + var ReactCurrentCache = { + current: null + }; -function memo(type, compare) { - { - if (!isValidElementType(type)) { - error( - "memo: The first argument must be a component. Instead " + - "received: %s", - type === null ? "null" : typeof type - ); + var UNTERMINATED = 0; + var TERMINATED = 1; + var ERRORED = 2; + + function createCacheRoot() { + return new WeakMap(); } - } - - var elementType = { - $$typeof: REACT_MEMO_TYPE, - type: type, - compare: compare === undefined ? null : compare - }; - - { - var ownName; - Object.defineProperty(elementType, "displayName", { - enumerable: false, - configurable: true, - get: function () { - return ownName; - }, - set: function (name) { - ownName = name; // The inner component shouldn't inherit this display name in most cases, - // because the component may be used elsewhere. - // But it's nice for anonymous functions to inherit the name, - // so that our component-stack generation logic will display their frames. - // An anonymous function generally suggests a pattern like: - // React.memo((props) => {...}); - // This kind of inner function is not used elsewhere so the side effect is okay. - if (!type.name && !type.displayName) { - type.displayName = name; - } - } - }); - } + function createCacheNode() { + return { + s: UNTERMINATED, + // status, represents whether the cached computation returned a value or threw an error + v: undefined, + // value, either the cached result or an error, depending on s + o: null, + // object cache, a WeakMap where non-primitive arguments are stored + p: null // primitive cache, a regular Map where primitive arguments are stored. + }; + } - return elementType; -} + function cache(fn) { + return function () { + var dispatcher = ReactCurrentCache.current; -/** - * Keeps track of the current Cache dispatcher. - */ -var ReactCurrentCache = { - current: null -}; + if (!dispatcher) { + // If there is no dispatcher, then we treat this as not being cached. + // $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code. + return fn.apply(null, arguments); + } -var UNTERMINATED = 0; -var TERMINATED = 1; -var ERRORED = 2; + var fnMap = dispatcher.getCacheForType(createCacheRoot); + var fnNode = fnMap.get(fn); + var cacheNode; -function createCacheRoot() { - return new WeakMap(); -} + if (fnNode === undefined) { + cacheNode = createCacheNode(); + fnMap.set(fn, cacheNode); + } else { + cacheNode = fnNode; + } -function createCacheNode() { - return { - s: UNTERMINATED, - // status, represents whether the cached computation returned a value or threw an error - v: undefined, - // value, either the cached result or an error, depending on s - o: null, - // object cache, a WeakMap where non-primitive arguments are stored - p: null // primitive cache, a regular Map where primitive arguments are stored. - }; -} + for (var i = 0, l = arguments.length; i < l; i++) { + var arg = arguments[i]; -function cache(fn) { - return function () { - var dispatcher = ReactCurrentCache.current; + if ( + typeof arg === "function" || + (typeof arg === "object" && arg !== null) + ) { + // Objects go into a WeakMap + var objectCache = cacheNode.o; - if (!dispatcher) { - // If there is no dispatcher, then we treat this as not being cached. - // $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code. - return fn.apply(null, arguments); - } + if (objectCache === null) { + cacheNode.o = objectCache = new WeakMap(); + } - var fnMap = dispatcher.getCacheForType(createCacheRoot); - var fnNode = fnMap.get(fn); - var cacheNode; + var objectNode = objectCache.get(arg); - if (fnNode === undefined) { - cacheNode = createCacheNode(); - fnMap.set(fn, cacheNode); - } else { - cacheNode = fnNode; - } + if (objectNode === undefined) { + cacheNode = createCacheNode(); + objectCache.set(arg, cacheNode); + } else { + cacheNode = objectNode; + } + } else { + // Primitives go into a regular Map + var primitiveCache = cacheNode.p; - for (var i = 0, l = arguments.length; i < l; i++) { - var arg = arguments[i]; + if (primitiveCache === null) { + cacheNode.p = primitiveCache = new Map(); + } - if ( - typeof arg === "function" || - (typeof arg === "object" && arg !== null) - ) { - // Objects go into a WeakMap - var objectCache = cacheNode.o; + var primitiveNode = primitiveCache.get(arg); - if (objectCache === null) { - cacheNode.o = objectCache = new WeakMap(); + if (primitiveNode === undefined) { + cacheNode = createCacheNode(); + primitiveCache.set(arg, cacheNode); + } else { + cacheNode = primitiveNode; + } + } } - var objectNode = objectCache.get(arg); - - if (objectNode === undefined) { - cacheNode = createCacheNode(); - objectCache.set(arg, cacheNode); - } else { - cacheNode = objectNode; + if (cacheNode.s === TERMINATED) { + return cacheNode.v; } - } else { - // Primitives go into a regular Map - var primitiveCache = cacheNode.p; - if (primitiveCache === null) { - cacheNode.p = primitiveCache = new Map(); + if (cacheNode.s === ERRORED) { + throw cacheNode.v; } - var primitiveNode = primitiveCache.get(arg); - - if (primitiveNode === undefined) { - cacheNode = createCacheNode(); - primitiveCache.set(arg, cacheNode); - } else { - cacheNode = primitiveNode; + try { + // $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code. + var result = fn.apply(null, arguments); + var terminatedNode = cacheNode; + terminatedNode.s = TERMINATED; + terminatedNode.v = result; + return result; + } catch (error) { + // We store the first error that's thrown and rethrow it. + var erroredNode = cacheNode; + erroredNode.s = ERRORED; + erroredNode.v = error; + throw error; } - } + }; } - if (cacheNode.s === TERMINATED) { - return cacheNode.v; - } + /** + * Keeps track of the current dispatcher. + */ + var ReactCurrentDispatcher$1 = { + current: null + }; - if (cacheNode.s === ERRORED) { - throw cacheNode.v; - } + function resolveDispatcher() { + var dispatcher = ReactCurrentDispatcher$1.current; - try { - // $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code. - var result = fn.apply(null, arguments); - var terminatedNode = cacheNode; - terminatedNode.s = TERMINATED; - terminatedNode.v = result; - return result; - } catch (error) { - // We store the first error that's thrown and rethrow it. - var erroredNode = cacheNode; - erroredNode.s = ERRORED; - erroredNode.v = error; - throw error; - } - }; -} + { + if (dispatcher === null) { + 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." + ); + } + } // Will result in a null access error if accessed outside render phase. We + // intentionally don't throw our own error because this is in a hot path. + // Also helps ensure this is inlined. -/** - * Keeps track of the current dispatcher. - */ -var ReactCurrentDispatcher$1 = { - current: null -}; - -function resolveDispatcher() { - var dispatcher = ReactCurrentDispatcher$1.current; - - { - if (dispatcher === null) { - 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." - ); + return dispatcher; } - } // Will result in a null access error if accessed outside render phase. We - // intentionally don't throw our own error because this is in a hot path. - // Also helps ensure this is inlined. - - return dispatcher; -} - -function getCacheSignal() { - var dispatcher = ReactCurrentCache.current; - - if (!dispatcher) { - // If we have no cache to associate with this call, then we don't know - // its lifetime. We abort early since that's safer than letting it live - // for ever. Unlike just caching which can be a functional noop outside - // of React, these should generally always be associated with some React - // render but we're not limiting quite as much as making it a Hook. - // It's safer than erroring early at runtime. - var controller = new AbortController(); - var reason = new Error( - "This CacheSignal was requested outside React which means that it is " + - "immediately aborted." - ); - controller.abort(reason); - return controller.signal; - } - - return dispatcher.getCacheSignal(); -} -function getCacheForType(resourceType) { - var dispatcher = ReactCurrentCache.current; - if (!dispatcher) { - // If there is no dispatcher, then we treat this as not being cached. - return resourceType(); - } - - return dispatcher.getCacheForType(resourceType); -} -function useContext(Context) { - var dispatcher = resolveDispatcher(); - - { - // TODO: add a more generic warning for invalid values. - if (Context._context !== undefined) { - var realContext = Context._context; // Don't deduplicate because this legitimately causes bugs - // and nobody should be using this in existing code. - - if (realContext.Consumer === Context) { - error( - "Calling useContext(Context.Consumer) is not supported, may cause bugs, and will be " + - "removed in a future major release. Did you mean to call useContext(Context) instead?" - ); - } else if (realContext.Provider === Context) { - error( - "Calling useContext(Context.Provider) is not supported. " + - "Did you mean to call useContext(Context) instead?" + function getCacheSignal() { + var dispatcher = ReactCurrentCache.current; + + if (!dispatcher) { + // If we have no cache to associate with this call, then we don't know + // its lifetime. We abort early since that's safer than letting it live + // for ever. Unlike just caching which can be a functional noop outside + // of React, these should generally always be associated with some React + // render but we're not limiting quite as much as making it a Hook. + // It's safer than erroring early at runtime. + var controller = new AbortController(); + var reason = new Error( + "This CacheSignal was requested outside React which means that it is " + + "immediately aborted." ); + controller.abort(reason); + return controller.signal; } - } - } - return dispatcher.useContext(Context); -} -function useState(initialState) { - var dispatcher = resolveDispatcher(); - return dispatcher.useState(initialState); -} -function useReducer(reducer, initialArg, init) { - var dispatcher = resolveDispatcher(); - return dispatcher.useReducer(reducer, initialArg, init); -} -function useRef(initialValue) { - var dispatcher = resolveDispatcher(); - return dispatcher.useRef(initialValue); -} -function useEffect(create, deps) { - var dispatcher = resolveDispatcher(); - return dispatcher.useEffect(create, deps); -} -function useInsertionEffect(create, deps) { - var dispatcher = resolveDispatcher(); - return dispatcher.useInsertionEffect(create, deps); -} -function useLayoutEffect(create, deps) { - var dispatcher = resolveDispatcher(); - return dispatcher.useLayoutEffect(create, deps); -} -function useCallback(callback, deps) { - var dispatcher = resolveDispatcher(); - return dispatcher.useCallback(callback, deps); -} -function useMemo(create, deps) { - var dispatcher = resolveDispatcher(); - return dispatcher.useMemo(create, deps); -} -function useImperativeHandle(ref, create, deps) { - var dispatcher = resolveDispatcher(); - return dispatcher.useImperativeHandle(ref, create, deps); -} -function useDebugValue(value, formatterFn) { - { - var dispatcher = resolveDispatcher(); - return dispatcher.useDebugValue(value, formatterFn); - } -} -function useTransition() { - var dispatcher = resolveDispatcher(); - return dispatcher.useTransition(); -} -function useDeferredValue(value, initialValue) { - var dispatcher = resolveDispatcher(); - return dispatcher.useDeferredValue(value, initialValue); -} -function useId() { - var dispatcher = resolveDispatcher(); - return dispatcher.useId(); -} -function useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { - var dispatcher = resolveDispatcher(); - return dispatcher.useSyncExternalStore( - subscribe, - getSnapshot, - getServerSnapshot - ); -} -function useCacheRefresh() { - var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional + return dispatcher.getCacheSignal(); + } + function getCacheForType(resourceType) { + var dispatcher = ReactCurrentCache.current; - return dispatcher.useCacheRefresh(); -} -function use(usable) { - var dispatcher = resolveDispatcher(); - return dispatcher.use(usable); -} -function useMemoCache(size) { - var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional + if (!dispatcher) { + // If there is no dispatcher, then we treat this as not being cached. + return resourceType(); + } - return dispatcher.useMemoCache(size); -} -function useEffectEvent(callback) { - var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional + return dispatcher.getCacheForType(resourceType); + } + function useContext(Context) { + var dispatcher = resolveDispatcher(); - return dispatcher.useEffectEvent(callback); -} -function useOptimistic(passthrough, reducer) { - var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional + { + // TODO: add a more generic warning for invalid values. + if (Context._context !== undefined) { + var realContext = Context._context; // Don't deduplicate because this legitimately causes bugs + // and nobody should be using this in existing code. - return dispatcher.useOptimistic(passthrough, reducer); -} + if (realContext.Consumer === Context) { + error( + "Calling useContext(Context.Consumer) is not supported, may cause bugs, and will be " + + "removed in a future major release. Did you mean to call useContext(Context) instead?" + ); + } else if (realContext.Provider === Context) { + error( + "Calling useContext(Context.Provider) is not supported. " + + "Did you mean to call useContext(Context) instead?" + ); + } + } + } -// Helpers to patch console.logs to avoid logging during side-effect free -// replaying on render function. This currently only patches the object -// lazily which won't cover if the log function was extracted eagerly. -// We could also eagerly patch the method. -var disabledDepth = 0; -var prevLog; -var prevInfo; -var prevWarn; -var prevError; -var prevGroup; -var prevGroupCollapsed; -var prevGroupEnd; - -function disabledLog() {} - -disabledLog.__reactDisabledLog = true; -function disableLogs() { - { - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - prevLog = console.log; - prevInfo = console.info; - prevWarn = console.warn; - prevError = console.error; - prevGroup = console.group; - prevGroupCollapsed = console.groupCollapsed; - prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 - - var props = { - configurable: true, - enumerable: true, - value: disabledLog, - writable: true - }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. - - Object.defineProperties(console, { - info: props, - log: props, - warn: props, - error: props, - group: props, - groupCollapsed: props, - groupEnd: props - }); - /* eslint-enable react-internal/no-production-logging */ + return dispatcher.useContext(Context); } - - disabledDepth++; - } -} -function reenableLogs() { - { - disabledDepth--; - - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - var props = { - configurable: true, - enumerable: true, - writable: true - }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. - - Object.defineProperties(console, { - log: assign({}, props, { - value: prevLog - }), - info: assign({}, props, { - value: prevInfo - }), - warn: assign({}, props, { - value: prevWarn - }), - error: assign({}, props, { - value: prevError - }), - group: assign({}, props, { - value: prevGroup - }), - groupCollapsed: assign({}, props, { - value: prevGroupCollapsed - }), - groupEnd: assign({}, props, { - value: prevGroupEnd - }) - }); - /* eslint-enable react-internal/no-production-logging */ + function useState(initialState) { + var dispatcher = resolveDispatcher(); + return dispatcher.useState(initialState); } - - if (disabledDepth < 0) { - error( - "disabledDepth fell below zero. " + - "This is a bug in React. Please file an issue." + function useReducer(reducer, initialArg, init) { + var dispatcher = resolveDispatcher(); + return dispatcher.useReducer(reducer, initialArg, init); + } + function useRef(initialValue) { + var dispatcher = resolveDispatcher(); + return dispatcher.useRef(initialValue); + } + function useEffect(create, deps) { + var dispatcher = resolveDispatcher(); + return dispatcher.useEffect(create, deps); + } + function useInsertionEffect(create, deps) { + var dispatcher = resolveDispatcher(); + return dispatcher.useInsertionEffect(create, deps); + } + function useLayoutEffect(create, deps) { + var dispatcher = resolveDispatcher(); + return dispatcher.useLayoutEffect(create, deps); + } + function useCallback(callback, deps) { + var dispatcher = resolveDispatcher(); + return dispatcher.useCallback(callback, deps); + } + function useMemo(create, deps) { + var dispatcher = resolveDispatcher(); + return dispatcher.useMemo(create, deps); + } + function useImperativeHandle(ref, create, deps) { + var dispatcher = resolveDispatcher(); + return dispatcher.useImperativeHandle(ref, create, deps); + } + function useDebugValue(value, formatterFn) { + { + var dispatcher = resolveDispatcher(); + return dispatcher.useDebugValue(value, formatterFn); + } + } + function useTransition() { + var dispatcher = resolveDispatcher(); + return dispatcher.useTransition(); + } + function useDeferredValue(value, initialValue) { + var dispatcher = resolveDispatcher(); + return dispatcher.useDeferredValue(value, initialValue); + } + function useId() { + var dispatcher = resolveDispatcher(); + return dispatcher.useId(); + } + function useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { + var dispatcher = resolveDispatcher(); + return dispatcher.useSyncExternalStore( + subscribe, + getSnapshot, + getServerSnapshot ); } - } -} - -/** - * Keeps track of the current batch's configuration such as how long an update - * should suspend for if it needs to. - */ -var ReactCurrentBatchConfig = { - transition: null -}; - -var ReactCurrentActQueue = { - current: null, - // Used to reproduce behavior of `batchedUpdates` in legacy mode. - isBatchingLegacy: false, - didScheduleLegacyUpdate: false, - // Tracks whether something called `use` during the current batch of work. - // Determines whether we should yield to microtasks to unwrap already resolved - // promises without suspending. - didUsePromise: false -}; - -var ReactDebugCurrentFrame$2 = {}; -var currentExtraStackFrame = null; -function setExtraStackFrame(stack) { - { - currentExtraStackFrame = stack; - } -} + function useCacheRefresh() { + var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional -{ - ReactDebugCurrentFrame$2.setExtraStackFrame = function (stack) { - { - currentExtraStackFrame = stack; + return dispatcher.useCacheRefresh(); } - }; // Stack implementation injected by the current renderer. - - ReactDebugCurrentFrame$2.getCurrentStack = null; - - ReactDebugCurrentFrame$2.getStackAddendum = function () { - var stack = ""; // Add an extra top frame while an element is being validated - - if (currentExtraStackFrame) { - stack += currentExtraStackFrame; - } // Delegate to the injected renderer-specific implementation - - var impl = ReactDebugCurrentFrame$2.getCurrentStack; + function use(usable) { + var dispatcher = resolveDispatcher(); + return dispatcher.use(usable); + } + function useMemoCache(size) { + var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional - if (impl) { - stack += impl() || ""; + return dispatcher.useMemoCache(size); } + function useEffectEvent(callback) { + var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional - return stack; - }; -} + return dispatcher.useEffectEvent(callback); + } + function useOptimistic(passthrough, reducer) { + var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional -var ReactSharedInternals = { - ReactCurrentDispatcher: ReactCurrentDispatcher$1, - ReactCurrentCache: ReactCurrentCache, - ReactCurrentBatchConfig: ReactCurrentBatchConfig, - ReactCurrentOwner: ReactCurrentOwner$2 -}; + return dispatcher.useOptimistic(passthrough, reducer); + } -{ - ReactSharedInternals.ReactDebugCurrentFrame = ReactDebugCurrentFrame$2; - ReactSharedInternals.ReactCurrentActQueue = ReactCurrentActQueue; -} + // Helpers to patch console.logs to avoid logging during side-effect free + // replaying on render function. This currently only patches the object + // lazily which won't cover if the log function was extracted eagerly. + // We could also eagerly patch the method. + var disabledDepth = 0; + var prevLog; + var prevInfo; + var prevWarn; + var prevError; + var prevGroup; + var prevGroupCollapsed; + var prevGroupEnd; + + function disabledLog() {} + + disabledLog.__reactDisabledLog = true; + function disableLogs() { + { + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + prevLog = console.log; + prevInfo = console.info; + prevWarn = console.warn; + prevError = console.error; + prevGroup = console.group; + prevGroupCollapsed = console.groupCollapsed; + prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 + + var props = { + configurable: true, + enumerable: true, + value: disabledLog, + writable: true + }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. + + Object.defineProperties(console, { + info: props, + log: props, + warn: props, + error: props, + group: props, + groupCollapsed: props, + groupEnd: props + }); + /* eslint-enable react-internal/no-production-logging */ + } -var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; -var prefix; -function describeBuiltInComponentFrame(name, source, ownerFn) { - { - if (prefix === undefined) { - // Extract the VM specific prefix used by each line. - try { - throw Error(); - } catch (x) { - var match = x.stack.trim().match(/\n( *(at )?)/); - prefix = (match && match[1]) || ""; + disabledDepth++; } - } // We use the prefix to ensure our stacks line up with native stack frames. - - return "\n" + prefix + name; - } -} -var reentry = false; -var componentFrameCache; - -{ - var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; - componentFrameCache = new PossiblyWeakMap(); -} - -function describeNativeComponentFrame(fn, construct) { - // If something asked for a stack inside a fake render, it should get ignored. - if (!fn || reentry) { - return ""; - } - - { - var frame = componentFrameCache.get(fn); - - if (frame !== undefined) { - return frame; } - } - - var control; - reentry = true; - var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. - - Error.prepareStackTrace = undefined; - var previousDispatcher; + function reenableLogs() { + { + disabledDepth--; + + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + var props = { + configurable: true, + enumerable: true, + writable: true + }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. + + Object.defineProperties(console, { + log: assign({}, props, { + value: prevLog + }), + info: assign({}, props, { + value: prevInfo + }), + warn: assign({}, props, { + value: prevWarn + }), + error: assign({}, props, { + value: prevError + }), + group: assign({}, props, { + value: prevGroup + }), + groupCollapsed: assign({}, props, { + value: prevGroupCollapsed + }), + groupEnd: assign({}, props, { + value: prevGroupEnd + }) + }); + /* eslint-enable react-internal/no-production-logging */ + } - { - previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function - // for warnings. + if (disabledDepth < 0) { + error( + "disabledDepth fell below zero. " + + "This is a bug in React. Please file an issue." + ); + } + } + } - ReactCurrentDispatcher.current = null; - disableLogs(); - } + /** + * Keeps track of the current batch's configuration such as how long an update + * should suspend for if it needs to. + */ + var ReactCurrentBatchConfig = { + transition: null + }; - try { - // This should throw. - if (construct) { - // Something should be setting the props in the constructor. - var Fake = function () { - throw Error(); - }; // $FlowFixMe[prop-missing] + var ReactCurrentActQueue = { + current: null, + // Used to reproduce behavior of `batchedUpdates` in legacy mode. + isBatchingLegacy: false, + didScheduleLegacyUpdate: false, + // Tracks whether something called `use` during the current batch of work. + // Determines whether we should yield to microtasks to unwrap already resolved + // promises without suspending. + didUsePromise: false + }; - Object.defineProperty(Fake.prototype, "props", { - set: function () { - // We use a throwing setter instead of frozen or non-writable props - // because that won't throw in a non-strict mode function. - throw Error(); - } - }); + var ReactDebugCurrentFrame$2 = {}; + var currentExtraStackFrame = null; + function setExtraStackFrame(stack) { + { + currentExtraStackFrame = stack; + } + } - if (typeof Reflect === "object" && Reflect.construct) { - // We construct a different control for this case to include any extra - // frames added by the construct call. - try { - Reflect.construct(Fake, []); - } catch (x) { - control = x; + { + ReactDebugCurrentFrame$2.setExtraStackFrame = function (stack) { + { + currentExtraStackFrame = stack; } + }; // Stack implementation injected by the current renderer. - Reflect.construct(fn, [], Fake); - } else { - try { - Fake.call(); - } catch (x) { - control = x; - } // $FlowFixMe[prop-missing] found when upgrading Flow + ReactDebugCurrentFrame$2.getCurrentStack = null; - fn.call(Fake.prototype); - } - } else { - try { - throw Error(); - } catch (x) { - control = x; - } // TODO(luna): This will currently only throw if the function component - // tries to access React/ReactDOM/props. We should probably make this throw - // in simple components too - - var maybePromise = fn(); // If the function component returns a promise, it's likely an async - // component, which we don't yet support. Attach a noop catch handler to - // silence the error. - // TODO: Implement component stacks for async client components? - - if (maybePromise && typeof maybePromise.catch === "function") { - maybePromise.catch(function () {}); - } - } - } catch (sample) { - // This is inlined manually because closure doesn't do it for us. - if (sample && control && typeof sample.stack === "string") { - // This extracts the first frame from the sample that isn't also in the control. - // Skipping one frame that we assume is the frame that calls the two. - var sampleLines = sample.stack.split("\n"); - var controlLines = control.stack.split("\n"); - var s = sampleLines.length - 1; - var c = controlLines.length - 1; - - while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { - // We expect at least one stack frame to be shared. - // Typically this will be the root most one. However, stack frames may be - // cut off due to maximum stack limits. In this case, one maybe cut off - // earlier than the other. We assume that the sample is longer or the same - // and there for cut off earlier. So we should find the root most frame in - // the sample somewhere in the control. - c--; - } - - for (; s >= 1 && c >= 0; s--, c--) { - // Next we find the first one that isn't the same which should be the - // frame that called our sample function and the control. - if (sampleLines[s] !== controlLines[c]) { - // In V8, the first line is describing the message but other VMs don't. - // If we're about to return the first line, and the control is also on the same - // line, that's a pretty good indicator that our sample threw at same line as - // the control. I.e. before we entered the sample frame. So we ignore this result. - // This can happen if you passed a class to function component, or non-function. - if (s !== 1 || c !== 1) { - do { - s--; - c--; // We may still have similar intermediate frames from the construct call. - // The next one that isn't the same should be our match though. - - if (c < 0 || sampleLines[s] !== controlLines[c]) { - // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. - var _frame = "\n" + sampleLines[s].replace(" at new ", " at "); // If our component frame is labeled "" - // but we have a user-provided "displayName" - // splice it in to make the stack more readable. - - if (fn.displayName && _frame.includes("")) { - _frame = _frame.replace("", fn.displayName); - } + ReactDebugCurrentFrame$2.getStackAddendum = function () { + var stack = ""; // Add an extra top frame while an element is being validated - { - if (typeof fn === "function") { - componentFrameCache.set(fn, _frame); - } - } // Return the line we found. + if (currentExtraStackFrame) { + stack += currentExtraStackFrame; + } // Delegate to the injected renderer-specific implementation - return _frame; - } - } while (s >= 1 && c >= 0); - } + var impl = ReactDebugCurrentFrame$2.getCurrentStack; - break; + if (impl) { + stack += impl() || ""; } - } - } - } finally { - reentry = false; - { - ReactCurrentDispatcher.current = previousDispatcher; - reenableLogs(); + return stack; + }; } - Error.prepareStackTrace = previousPrepareStackTrace; - } // Fallback to just using the name if we couldn't make it throw. - - var name = fn ? fn.displayName || fn.name : ""; - var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ""; + var ReactSharedInternals = { + ReactCurrentDispatcher: ReactCurrentDispatcher$1, + ReactCurrentCache: ReactCurrentCache, + ReactCurrentBatchConfig: ReactCurrentBatchConfig, + ReactCurrentOwner: ReactCurrentOwner$2 + }; - { - if (typeof fn === "function") { - componentFrameCache.set(fn, syntheticFrame); + { + ReactSharedInternals.ReactDebugCurrentFrame = ReactDebugCurrentFrame$2; + ReactSharedInternals.ReactCurrentActQueue = ReactCurrentActQueue; } - } - - return syntheticFrame; -} -function describeFunctionComponentFrame(fn, source, ownerFn) { - { - return describeNativeComponentFrame(fn, false); - } -} -function shouldConstruct(Component) { - var prototype = Component.prototype; - return !!(prototype && prototype.isReactComponent); -} + var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; + var prefix; + function describeBuiltInComponentFrame(name, source, ownerFn) { + { + if (prefix === undefined) { + // Extract the VM specific prefix used by each line. + try { + throw Error(); + } catch (x) { + var match = x.stack.trim().match(/\n( *(at )?)/); + prefix = (match && match[1]) || ""; + } + } // We use the prefix to ensure our stacks line up with native stack frames. -function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { - if (type == null) { - return ""; - } + return "\n" + prefix + name; + } + } + var reentry = false; + var componentFrameCache; - if (typeof type === "function") { { - return describeNativeComponentFrame(type, shouldConstruct(type)); + var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; + componentFrameCache = new PossiblyWeakMap(); } - } - if (typeof type === "string") { - return describeBuiltInComponentFrame(type); - } + function describeNativeComponentFrame(fn, construct) { + // If something asked for a stack inside a fake render, it should get ignored. + if (!fn || reentry) { + return ""; + } - switch (type) { - case REACT_SUSPENSE_TYPE: - return describeBuiltInComponentFrame("Suspense"); + { + var frame = componentFrameCache.get(fn); - case REACT_SUSPENSE_LIST_TYPE: - return describeBuiltInComponentFrame("SuspenseList"); - } + if (frame !== undefined) { + return frame; + } + } - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_FORWARD_REF_TYPE: - return describeFunctionComponentFrame(type.render); + var control; + reentry = true; + var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. - case REACT_MEMO_TYPE: - // Memo may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); + Error.prepareStackTrace = undefined; + var previousDispatcher; - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + { + previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function + // for warnings. - try { - // Lazy may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV( - init(payload), - source, - ownerFn - ); - } catch (x) {} + ReactCurrentDispatcher.current = null; + disableLogs(); } - } - } - - return ""; -} - -var loggedTypeFailures = {}; -var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; -function setCurrentlyValidatingElement$2(element) { - { - if (element) { - var owner = element._owner; - var stack = describeUnknownElementTypeFrameInDEV( - element.type, - element._source, - owner ? owner.type : null - ); - ReactDebugCurrentFrame$1.setExtraStackFrame(stack); - } else { - ReactDebugCurrentFrame$1.setExtraStackFrame(null); - } - } -} + try { + // This should throw. + if (construct) { + // Something should be setting the props in the constructor. + var Fake = function () { + throw Error(); + }; // $FlowFixMe[prop-missing] + + Object.defineProperty(Fake.prototype, "props", { + set: function () { + // We use a throwing setter instead of frozen or non-writable props + // because that won't throw in a non-strict mode function. + throw Error(); + } + }); -function checkPropTypes(typeSpecs, values, location, componentName, element) { - { - // $FlowFixMe[incompatible-use] This is okay but Flow doesn't know it. - var has = Function.call.bind(hasOwnProperty); + if (typeof Reflect === "object" && Reflect.construct) { + // We construct a different control for this case to include any extra + // frames added by the construct call. + try { + Reflect.construct(Fake, []); + } catch (x) { + control = x; + } - for (var typeSpecName in typeSpecs) { - if (has(typeSpecs, typeSpecName)) { - var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to - // fail the render phase where it didn't fail before. So we log it. - // After these have been cleaned up, we'll let them throw. + Reflect.construct(fn, [], Fake); + } else { + try { + Fake.call(); + } catch (x) { + control = x; + } // $FlowFixMe[prop-missing] found when upgrading Flow - try { - // This is intentionally an invariant that gets caught. It's the same - // behavior as without this statement except with a better message. - if (typeof typeSpecs[typeSpecName] !== "function") { - // eslint-disable-next-line react-internal/prod-error-codes - 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`." - ); - err.name = "Invariant Violation"; - throw err; + fn.call(Fake.prototype); + } + } else { + try { + throw Error(); + } catch (x) { + control = x; + } // TODO(luna): This will currently only throw if the function component + // tries to access React/ReactDOM/props. We should probably make this throw + // in simple components too + + var maybePromise = fn(); // If the function component returns a promise, it's likely an async + // component, which we don't yet support. Attach a noop catch handler to + // silence the error. + // TODO: Implement component stacks for async client components? + + if (maybePromise && typeof maybePromise.catch === "function") { + maybePromise.catch(function () {}); } - - error$1 = typeSpecs[typeSpecName]( - values, - typeSpecName, - componentName, - location, - null, - "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" - ); - } catch (ex) { - error$1 = ex; } + } catch (sample) { + // This is inlined manually because closure doesn't do it for us. + if (sample && control && typeof sample.stack === "string") { + // This extracts the first frame from the sample that isn't also in the control. + // Skipping one frame that we assume is the frame that calls the two. + var sampleLines = sample.stack.split("\n"); + var controlLines = control.stack.split("\n"); + var s = sampleLines.length - 1; + var c = controlLines.length - 1; + + while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { + // We expect at least one stack frame to be shared. + // Typically this will be the root most one. However, stack frames may be + // cut off due to maximum stack limits. In this case, one maybe cut off + // earlier than the other. We assume that the sample is longer or the same + // and there for cut off earlier. So we should find the root most frame in + // the sample somewhere in the control. + c--; + } - if (error$1 && !(error$1 instanceof Error)) { - setCurrentlyValidatingElement$2(element); + for (; s >= 1 && c >= 0; s--, c--) { + // Next we find the first one that isn't the same which should be the + // frame that called our sample function and the control. + if (sampleLines[s] !== controlLines[c]) { + // In V8, the first line is describing the message but other VMs don't. + // If we're about to return the first line, and the control is also on the same + // line, that's a pretty good indicator that our sample threw at same line as + // the control. I.e. before we entered the sample frame. So we ignore this result. + // This can happen if you passed a class to function component, or non-function. + if (s !== 1 || c !== 1) { + do { + s--; + c--; // We may still have similar intermediate frames from the construct call. + // The next one that isn't the same should be our match though. + + if (c < 0 || sampleLines[s] !== controlLines[c]) { + // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. + var _frame = + "\n" + sampleLines[s].replace(" at new ", " at "); // If our component frame is labeled "" + // but we have a user-provided "displayName" + // splice it in to make the stack more readable. + + if (fn.displayName && _frame.includes("")) { + _frame = _frame.replace("", fn.displayName); + } + + { + if (typeof fn === "function") { + componentFrameCache.set(fn, _frame); + } + } // Return the line we found. + + return _frame; + } + } while (s >= 1 && c >= 0); + } - 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 - ); + break; + } + } + } + } finally { + reentry = false; - setCurrentlyValidatingElement$2(null); + { + ReactCurrentDispatcher.current = previousDispatcher; + reenableLogs(); } - if ( - error$1 instanceof Error && - !(error$1.message in loggedTypeFailures) - ) { - // Only monitor this failure once because there tends to be a lot of the - // same error. - loggedTypeFailures[error$1.message] = true; - setCurrentlyValidatingElement$2(element); + Error.prepareStackTrace = previousPrepareStackTrace; + } // Fallback to just using the name if we couldn't make it throw. - error("Failed %s type: %s", location, error$1.message); + var name = fn ? fn.displayName || fn.name : ""; + var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ""; - setCurrentlyValidatingElement$2(null); + { + if (typeof fn === "function") { + componentFrameCache.set(fn, syntheticFrame); } } - } - } -} - -var REACT_CLIENT_REFERENCE$1 = Symbol.for("react.client.reference"); -function setCurrentlyValidatingElement$1(element) { - { - if (element) { - var owner = element._owner; - var stack = describeUnknownElementTypeFrameInDEV( - element.type, - element._source, - owner ? owner.type : null - ); - setExtraStackFrame(stack); - } else { - setExtraStackFrame(null); + return syntheticFrame; + } + function describeFunctionComponentFrame(fn, source, ownerFn) { + { + return describeNativeComponentFrame(fn, false); + } } - } -} -var propTypesMisspellWarningShown$1; + function shouldConstruct(Component) { + var prototype = Component.prototype; + return !!(prototype && prototype.isReactComponent); + } -{ - propTypesMisspellWarningShown$1 = false; -} + function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { + if (type == null) { + return ""; + } -function getDeclarationErrorAddendum$1() { - if (ReactCurrentOwner$2.current) { - var name = getComponentNameFromType(ReactCurrentOwner$2.current.type); + if (typeof type === "function") { + { + return describeNativeComponentFrame(type, shouldConstruct(type)); + } + } - if (name) { - return "\n\nCheck the render method of `" + name + "`."; - } - } + if (typeof type === "string") { + return describeBuiltInComponentFrame(type); + } - return ""; -} + switch (type) { + case REACT_SUSPENSE_TYPE: + return describeBuiltInComponentFrame("Suspense"); -function getSourceInfoErrorAddendum$1(source) { - if (source !== undefined) { - var fileName = source.fileName.replace(/^.*[\\\/]/, ""); - var lineNumber = source.lineNumber; - return "\n\nCheck your code at " + fileName + ":" + lineNumber + "."; - } + case REACT_SUSPENSE_LIST_TYPE: + return describeBuiltInComponentFrame("SuspenseList"); + } - return ""; -} + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_FORWARD_REF_TYPE: + return describeFunctionComponentFrame(type.render); + + case REACT_MEMO_TYPE: + // Memo may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + type.type, + source, + ownerFn + ); -function getSourceInfoErrorAddendumForProps(elementProps) { - if (elementProps !== null && elementProps !== undefined) { - return getSourceInfoErrorAddendum$1(elementProps.__source); - } + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; + + try { + // Lazy may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + init(payload), + source, + ownerFn + ); + } catch (x) {} + } + } + } - return ""; -} -/** - * Warn if there's no key explicitly set on dynamic arrays of children or - * object keys are not valid. This allows us to keep track of children between - * updates. - */ + return ""; + } -var ownerHasKeyUseWarning$1 = {}; + var loggedTypeFailures = {}; + var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; -function getCurrentComponentErrorInfo$1(parentType) { - var info = getDeclarationErrorAddendum$1(); + function setCurrentlyValidatingElement$2(element) { + { + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV( + element.type, + element._source, + owner ? owner.type : null + ); + ReactDebugCurrentFrame$1.setExtraStackFrame(stack); + } else { + ReactDebugCurrentFrame$1.setExtraStackFrame(null); + } + } + } - if (!info) { - var parentName = - typeof parentType === "string" - ? parentType - : parentType.displayName || parentType.name; + function checkPropTypes( + typeSpecs, + values, + location, + componentName, + element + ) { + { + // $FlowFixMe[incompatible-use] This is okay but Flow doesn't know it. + var has = Function.call.bind(hasOwnProperty); + + for (var typeSpecName in typeSpecs) { + if (has(typeSpecs, typeSpecName)) { + var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to + // fail the render phase where it didn't fail before. So we log it. + // After these have been cleaned up, we'll let them throw. + + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + if (typeof typeSpecs[typeSpecName] !== "function") { + // eslint-disable-next-line react-internal/prod-error-codes + 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`." + ); + err.name = "Invariant Violation"; + throw err; + } - if (parentName) { - info = "\n\nCheck the top-level render call using <" + parentName + ">."; - } - } + error$1 = typeSpecs[typeSpecName]( + values, + typeSpecName, + componentName, + location, + null, + "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" + ); + } catch (ex) { + error$1 = ex; + } - return info; -} -/** - * Warn if the element doesn't have an explicit key assigned to it. - * This element is in an array. The array could grow and shrink or be - * reordered. All children that haven't already been validated are required to - * have a "key" property assigned to it. Error statuses are cached so a warning - * will only be shown once. - * - * @internal - * @param {ReactElement} element Element that requires a key. - * @param {*} parentType element's parent's type. - */ + if (error$1 && !(error$1 instanceof Error)) { + setCurrentlyValidatingElement$2(element); -function validateExplicitKey$1(element, parentType) { - if (!element._store || element._store.validated || element.key != null) { - return; - } - - element._store.validated = true; - var currentComponentErrorInfo = getCurrentComponentErrorInfo$1(parentType); - - if (ownerHasKeyUseWarning$1[currentComponentErrorInfo]) { - return; - } - - ownerHasKeyUseWarning$1[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a - // property, it may be the creator of the child that's responsible for - // assigning it a key. - - var childOwner = ""; - - if ( - element && - element._owner && - element._owner !== ReactCurrentOwner$2.current - ) { - // Give the component that originally created this child. - childOwner = - " It was passed a child from " + - getComponentNameFromType(element._owner.type) + - "."; - } - - { - setCurrentlyValidatingElement$1(element); - - error( - 'Each child in a list should have a unique "key" prop.' + - "%s%s See https://reactjs.org/link/warning-keys for more information.", - currentComponentErrorInfo, - childOwner - ); - - setCurrentlyValidatingElement$1(null); - } -} -/** - * Ensure that every element either is passed in a static location, in an - * array with an explicit keys property defined, or in an object literal - * with valid key property. - * - * @internal - * @param {ReactNode} node Statically passed child of any type. - * @param {*} parentType node's parent's type. - */ + 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 + ); + + setCurrentlyValidatingElement$2(null); + } -function validateChildKeys$1(node, parentType) { - if (typeof node !== "object" || !node) { - return; - } + if ( + error$1 instanceof Error && + !(error$1.message in loggedTypeFailures) + ) { + // Only monitor this failure once because there tends to be a lot of the + // same error. + loggedTypeFailures[error$1.message] = true; + setCurrentlyValidatingElement$2(element); - if (node.$$typeof === REACT_CLIENT_REFERENCE$1); - else if (isArray(node)) { - for (var i = 0; i < node.length; i++) { - var child = node[i]; + error("Failed %s type: %s", location, error$1.message); - if (isValidElement$1(child)) { - validateExplicitKey$1(child, parentType); + setCurrentlyValidatingElement$2(null); + } + } + } } } - } else if (isValidElement$1(node)) { - // This element was passed in a valid location. - if (node._store) { - node._store.validated = true; - } - } else { - var iteratorFn = getIteratorFn(node); - if (typeof iteratorFn === "function") { - // Entry iterators used to provide implicit keys, - // but now we print a separate warning for them later. - if (iteratorFn !== node.entries) { - var iterator = iteratorFn.call(node); - var step; + var REACT_CLIENT_REFERENCE$1 = Symbol.for("react.client.reference"); - while (!(step = iterator.next()).done) { - if (isValidElement$1(step.value)) { - validateExplicitKey$1(step.value, parentType); - } + function setCurrentlyValidatingElement$1(element) { + { + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV( + element.type, + element._source, + owner ? owner.type : null + ); + setExtraStackFrame(stack); + } else { + setExtraStackFrame(null); } } } - } -} -/** - * Given an element, validate that its props follow the propTypes definition, - * provided by the type. - * - * @param {ReactElement} element - */ -function validatePropTypes$1(element) { - { - var type = element.type; + var propTypesMisspellWarningShown$1; - if (type === null || type === undefined || typeof type === "string") { - return; + { + propTypesMisspellWarningShown$1 = false; } - if (type.$$typeof === REACT_CLIENT_REFERENCE$1) { - return; + function getDeclarationErrorAddendum$1() { + if (ReactCurrentOwner$2.current) { + var name = getComponentNameFromType(ReactCurrentOwner$2.current.type); + + if (name) { + return "\n\nCheck the render method of `" + name + "`."; + } + } + + return ""; } - var propTypes; + function getSourceInfoErrorAddendum$1(source) { + if (source !== undefined) { + var fileName = source.fileName.replace(/^.*[\\\/]/, ""); + var lineNumber = source.lineNumber; + return "\n\nCheck your code at " + fileName + ":" + lineNumber + "."; + } - if (typeof type === "function") { - propTypes = type.propTypes; - } else if ( - typeof type === "object" && - (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here. - // Inner props are checked in the reconciler. - type.$$typeof === REACT_MEMO_TYPE) - ) { - propTypes = type.propTypes; - } else { - return; - } - - if (propTypes) { - // Intentionally inside to avoid triggering lazy initializers: - var name = getComponentNameFromType(type); - checkPropTypes(propTypes, element.props, "prop", name, element); - } else if ( - type.PropTypes !== undefined && - !propTypesMisspellWarningShown$1 - ) { - propTypesMisspellWarningShown$1 = true; // Intentionally inside to avoid triggering lazy initializers: + return ""; + } - var _name = getComponentNameFromType(type); + function getSourceInfoErrorAddendumForProps(elementProps) { + if (elementProps !== null && elementProps !== undefined) { + return getSourceInfoErrorAddendum$1(elementProps.__source); + } - error( - "Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?", - _name || "Unknown" - ); + return ""; } + /** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ + + var ownerHasKeyUseWarning$1 = {}; + + function getCurrentComponentErrorInfo$1(parentType) { + var info = getDeclarationErrorAddendum$1(); + + if (!info) { + var parentName = + typeof parentType === "string" + ? parentType + : parentType.displayName || parentType.name; + + if (parentName) { + info = + "\n\nCheck the top-level render call using <" + parentName + ">."; + } + } - if ( - typeof type.getDefaultProps === "function" && - !type.getDefaultProps.isReactClassApproved - ) { - error( - "getDefaultProps is only used on classic React.createClass " + - "definitions. Use a static property named `defaultProps` instead." - ); + return info; } - } -} -/** - * Given a fragment, validate that it can only be provided with fragment props - * @param {ReactElement} fragment - */ + /** + * Warn if the element doesn't have an explicit key assigned to it. + * This element is in an array. The array could grow and shrink or be + * reordered. All children that haven't already been validated are required to + * have a "key" property assigned to it. Error statuses are cached so a warning + * will only be shown once. + * + * @internal + * @param {ReactElement} element Element that requires a key. + * @param {*} parentType element's parent's type. + */ + + function validateExplicitKey$1(element, parentType) { + if (!element._store || element._store.validated || element.key != null) { + return; + } -function validateFragmentProps$1(fragment) { - { - var keys = Object.keys(fragment.props); + element._store.validated = true; + var currentComponentErrorInfo = + getCurrentComponentErrorInfo$1(parentType); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; + if (ownerHasKeyUseWarning$1[currentComponentErrorInfo]) { + return; + } - if (key !== "children" && key !== "key") { - setCurrentlyValidatingElement$1(fragment); + ownerHasKeyUseWarning$1[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a + // property, it may be the creator of the child that's responsible for + // assigning it a key. - error( - "Invalid prop `%s` supplied to `React.Fragment`. " + - "React.Fragment can only have `key` and `children` props.", - key - ); + var childOwner = ""; - setCurrentlyValidatingElement$1(null); - break; + if ( + element && + element._owner && + element._owner !== ReactCurrentOwner$2.current + ) { + // Give the component that originally created this child. + childOwner = + " It was passed a child from " + + getComponentNameFromType(element._owner.type) + + "."; } - } - if (fragment.ref !== null) { - setCurrentlyValidatingElement$1(fragment); + { + setCurrentlyValidatingElement$1(element); - error("Invalid attribute `ref` supplied to `React.Fragment`."); + error( + 'Each child in a list should have a unique "key" prop.' + + "%s%s See https://reactjs.org/link/warning-keys for more information.", + currentComponentErrorInfo, + childOwner + ); - setCurrentlyValidatingElement$1(null); + setCurrentlyValidatingElement$1(null); + } } - } -} -function createElementWithValidation(type, props, children) { - var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to - // succeed and there will likely be errors in render. + /** + * Ensure that every element either is passed in a static location, in an + * array with an explicit keys property defined, or in an object literal + * with valid key property. + * + * @internal + * @param {ReactNode} node Statically passed child of any type. + * @param {*} parentType node's parent's type. + */ + + function validateChildKeys$1(node, parentType) { + if (typeof node !== "object" || !node) { + return; + } - if (!validType) { - var info = ""; + if (node.$$typeof === REACT_CLIENT_REFERENCE$1); + else if (isArray(node)) { + for (var i = 0; i < node.length; i++) { + var child = node[i]; - if ( - type === undefined || - (typeof type === "object" && - type !== null && - Object.keys(type).length === 0) - ) { - 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."; + if (isValidElement$1(child)) { + validateExplicitKey$1(child, parentType); + } + } + } else if (isValidElement$1(node)) { + // This element was passed in a valid location. + if (node._store) { + node._store.validated = true; + } + } else { + var iteratorFn = getIteratorFn(node); + + if (typeof iteratorFn === "function") { + // Entry iterators used to provide implicit keys, + // but now we print a separate warning for them later. + if (iteratorFn !== node.entries) { + var iterator = iteratorFn.call(node); + var step; + + while (!(step = iterator.next()).done) { + if (isValidElement$1(step.value)) { + validateExplicitKey$1(step.value, parentType); + } + } + } + } + } } + /** + * Given an element, validate that its props follow the propTypes definition, + * provided by the type. + * + * @param {ReactElement} element + */ + + function validatePropTypes$1(element) { + { + var type = element.type; - var sourceInfo = getSourceInfoErrorAddendumForProps(props); + if (type === null || type === undefined || typeof type === "string") { + return; + } - if (sourceInfo) { - info += sourceInfo; - } else { - info += getDeclarationErrorAddendum$1(); - } + if (type.$$typeof === REACT_CLIENT_REFERENCE$1) { + return; + } - var typeString; + var propTypes; - if (type === null) { - typeString = "null"; - } else if (isArray(type)) { - typeString = "array"; - } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) { - typeString = - "<" + (getComponentNameFromType(type.type) || "Unknown") + " />"; - info = - " Did you accidentally export a JSX literal instead of a component?"; - } else { - typeString = typeof type; - } + if (typeof type === "function") { + propTypes = type.propTypes; + } else if ( + typeof type === "object" && + (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here. + // Inner props are checked in the reconciler. + type.$$typeof === REACT_MEMO_TYPE) + ) { + propTypes = type.propTypes; + } else { + return; + } - { - error( - "React.createElement: type is invalid -- expected a string (for " + - "built-in components) or a class/function (for composite " + - "components) but got: %s.%s", - typeString, - info - ); - } - } + if (propTypes) { + // Intentionally inside to avoid triggering lazy initializers: + var name = getComponentNameFromType(type); + checkPropTypes(propTypes, element.props, "prop", name, element); + } else if ( + type.PropTypes !== undefined && + !propTypesMisspellWarningShown$1 + ) { + propTypesMisspellWarningShown$1 = true; // Intentionally inside to avoid triggering lazy initializers: - var element = createElement$1.apply(this, arguments); // The result can be nullish if a mock or a custom function is used. - // TODO: Drop this when these are no longer allowed as the type argument. + var _name = getComponentNameFromType(type); - if (element == null) { - return element; - } // Skip key warning if the type isn't valid since our key validation logic - // doesn't expect a non-string/function type and can throw confusing errors. - // We don't want exception behavior to differ between dev and prod. - // (Rendering will throw with a helpful message and as soon as the type is - // fixed, the key warnings will appear.) + error( + "Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?", + _name || "Unknown" + ); + } - if (validType) { - for (var i = 2; i < arguments.length; i++) { - validateChildKeys$1(arguments[i], type); + if ( + typeof type.getDefaultProps === "function" && + !type.getDefaultProps.isReactClassApproved + ) { + error( + "getDefaultProps is only used on classic React.createClass " + + "definitions. Use a static property named `defaultProps` instead." + ); + } + } } - } + /** + * Given a fragment, validate that it can only be provided with fragment props + * @param {ReactElement} fragment + */ - if (type === REACT_FRAGMENT_TYPE) { - validateFragmentProps$1(element); - } else { - validatePropTypes$1(element); - } + function validateFragmentProps$1(fragment) { + { + var keys = Object.keys(fragment.props); - return element; -} -function cloneElementWithValidation(element, props, children) { - var newElement = cloneElement$1.apply(this, arguments); + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; - for (var i = 2; i < arguments.length; i++) { - validateChildKeys$1(arguments[i], newElement.type); - } + if (key !== "children" && key !== "key") { + setCurrentlyValidatingElement$1(fragment); - validatePropTypes$1(newElement); - return newElement; -} + error( + "Invalid prop `%s` supplied to `React.Fragment`. " + + "React.Fragment can only have `key` and `children` props.", + key + ); -function startTransition(scope, options) { - var prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = {}; - var currentTransition = ReactCurrentBatchConfig.transition; + setCurrentlyValidatingElement$1(null); + break; + } + } - { - ReactCurrentBatchConfig.transition._updatedFibers = new Set(); - } + if (fragment.ref !== null) { + setCurrentlyValidatingElement$1(fragment); - if (enableTransitionTracing) { - if (options !== undefined && options.name !== undefined) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - ReactCurrentBatchConfig.transition.name = options.name; // $FlowFixMe[incompatible-use] found when upgrading Flow + error("Invalid attribute `ref` supplied to `React.Fragment`."); - ReactCurrentBatchConfig.transition.startTime = -1; + setCurrentlyValidatingElement$1(null); + } + } } - } + function createElementWithValidation(type, props, children) { + var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to + // succeed and there will likely be errors in render. - try { - scope(); - } finally { - ReactCurrentBatchConfig.transition = prevTransition; + if (!validType) { + var info = ""; - { - if (prevTransition === null && currentTransition._updatedFibers) { - var updatedFibersCount = currentTransition._updatedFibers.size; + if ( + type === undefined || + (typeof type === "object" && + type !== null && + Object.keys(type).length === 0) + ) { + 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."; + } + + var sourceInfo = getSourceInfoErrorAddendumForProps(props); - currentTransition._updatedFibers.clear(); + if (sourceInfo) { + info += sourceInfo; + } else { + info += getDeclarationErrorAddendum$1(); + } + + var typeString; + + if (type === null) { + typeString = "null"; + } else if (isArray(type)) { + typeString = "array"; + } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) { + typeString = + "<" + (getComponentNameFromType(type.type) || "Unknown") + " />"; + info = + " Did you accidentally export a JSX literal instead of a component?"; + } else { + typeString = typeof type; + } - if (updatedFibersCount > 10) { - 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." + { + error( + "React.createElement: type is invalid -- expected a string (for " + + "built-in components) or a class/function (for composite " + + "components) but got: %s.%s", + typeString, + info ); } } - } - } -} -var didWarnAboutMessageChannel = false; -var enqueueTaskImpl = null; -function enqueueTask(task) { - if (enqueueTaskImpl === null) { - try { - // read require off the module object to get around the bundlers. - // we don't want them to detect a require and bundle a Node polyfill. - var requireString = ("require" + Math.random()).slice(0, 7); - var nodeRequire = module && module[requireString]; // assuming we're in node, let's try to get node's - // version of setImmediate, bypassing fake timers if any. - - enqueueTaskImpl = nodeRequire.call(module, "timers").setImmediate; - } catch (_err) { - // we're in a browser - // we can't use regular timers because they may still be faked - // so we try MessageChannel+postMessage instead - enqueueTaskImpl = function (callback) { - { - if (didWarnAboutMessageChannel === false) { - didWarnAboutMessageChannel = true; + var element = createElement$1.apply(this, arguments); // The result can be nullish if a mock or a custom function is used. + // TODO: Drop this when these are no longer allowed as the type argument. - if (typeof MessageChannel === "undefined") { - error( - "This browser does not have a MessageChannel implementation, " + - "so enqueuing tasks via await act(async () => ...) will fail. " + - "Please file an issue at https://github.com/facebook/react/issues " + - "if you encounter this warning." - ); - } - } + if (element == null) { + return element; + } // Skip key warning if the type isn't valid since our key validation logic + // doesn't expect a non-string/function type and can throw confusing errors. + // We don't want exception behavior to differ between dev and prod. + // (Rendering will throw with a helpful message and as soon as the type is + // fixed, the key warnings will appear.) + + if (validType) { + for (var i = 2; i < arguments.length; i++) { + validateChildKeys$1(arguments[i], type); } + } - var channel = new MessageChannel(); - channel.port1.onmessage = callback; - channel.port2.postMessage(undefined); - }; + if (type === REACT_FRAGMENT_TYPE) { + validateFragmentProps$1(element); + } else { + validatePropTypes$1(element); + } + + return element; } - } + function cloneElementWithValidation(element, props, children) { + var newElement = cloneElement$1.apply(this, arguments); - return enqueueTaskImpl(task); -} + for (var i = 2; i < arguments.length; i++) { + validateChildKeys$1(arguments[i], newElement.type); + } -// number of `act` scopes on the stack. + validatePropTypes$1(newElement); + return newElement; + } -var actScopeDepth = 0; // We only warn the first time you neglect to await an async `act` scope. + function startTransition(scope, options) { + var prevTransition = ReactCurrentBatchConfig.transition; + ReactCurrentBatchConfig.transition = {}; + var currentTransition = ReactCurrentBatchConfig.transition; -var didWarnNoAwaitAct = false; -function act(callback) { - { - // When ReactCurrentActQueue.current is not null, it signals to React that - // we're currently inside an `act` scope. React will push all its tasks to - // this queue instead of scheduling them with platform APIs. - // - // We set this to an empty array when we first enter an `act` scope, and - // only unset it once we've left the outermost `act` scope — remember that - // `act` calls can be nested. - // - // If we're already inside an `act` scope, reuse the existing queue. - var prevIsBatchingLegacy = ReactCurrentActQueue.isBatchingLegacy; - var prevActQueue = ReactCurrentActQueue.current; - var prevActScopeDepth = actScopeDepth; - actScopeDepth++; - var queue = (ReactCurrentActQueue.current = - prevActQueue !== null ? prevActQueue : []); // Used to reproduce behavior of `batchedUpdates` in legacy mode. Only - // set to `true` while the given callback is executed, not for updates - // triggered during an async event, because this is how the legacy - // implementation of `act` behaved. - - ReactCurrentActQueue.isBatchingLegacy = true; - var result; // This tracks whether the `act` call is awaited. In certain cases, not - // awaiting it is a mistake, so we will detect that and warn. - - var didAwaitActCall = false; - - try { - // Reset this to `false` right before entering the React work loop. The - // only place we ever read this fields is just below, right after running - // the callback. So we don't need to reset after the callback runs. - ReactCurrentActQueue.didScheduleLegacyUpdate = false; - result = callback(); - var didScheduleLegacyUpdate = - ReactCurrentActQueue.didScheduleLegacyUpdate; // Replicate behavior of original `act` implementation in legacy mode, - // which flushed updates immediately after the scope function exits, even - // if it's an async function. - - if (!prevIsBatchingLegacy && didScheduleLegacyUpdate) { - flushActQueue(queue); - } // `isBatchingLegacy` gets reset using the regular stack, not the async - // one used to track `act` scopes. Why, you may be wondering? Because - // that's how it worked before version 18. Yes, it's confusing! We should - // delete legacy mode!! - - ReactCurrentActQueue.isBatchingLegacy = prevIsBatchingLegacy; - } catch (error) { - // `isBatchingLegacy` gets reset using the regular stack, not the async - // one used to track `act` scopes. Why, you may be wondering? Because - // that's how it worked before version 18. Yes, it's confusing! We should - // delete legacy mode!! - ReactCurrentActQueue.isBatchingLegacy = prevIsBatchingLegacy; - popActScope(prevActQueue, prevActScopeDepth); - throw error; - } + { + ReactCurrentBatchConfig.transition._updatedFibers = new Set(); + } - if ( - result !== null && - typeof result === "object" && // $FlowFixMe[method-unbinding] - typeof result.then === "function" - ) { - // A promise/thenable was returned from the callback. Wait for it to - // resolve before flushing the queue. - // - // If `act` were implemented as an async function, this whole block could - // be a single `await` call. That's really the only difference between - // this branch and the next one. - var thenable = result; // Warn if the an `act` call with an async scope is not awaited. In a - // future release, consider making this an error. + if (enableTransitionTracing) { + if (options !== undefined && options.name !== undefined) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + ReactCurrentBatchConfig.transition.name = options.name; // $FlowFixMe[incompatible-use] found when upgrading Flow - queueSeveralMicrotasks(function () { - if (!didAwaitActCall && !didWarnNoAwaitAct) { - didWarnNoAwaitAct = true; + ReactCurrentBatchConfig.transition.startTime = -1; + } + } - error( - "You called act(async () => ...) without await. " + - "This could lead to unexpected testing behaviour, " + - "interleaving multiple act calls and mixing their " + - "scopes. " + - "You should - await act(async () => ...);" - ); + try { + scope(); + } finally { + ReactCurrentBatchConfig.transition = prevTransition; + + { + if (prevTransition === null && currentTransition._updatedFibers) { + var updatedFibersCount = currentTransition._updatedFibers.size; + + currentTransition._updatedFibers.clear(); + + if (updatedFibersCount > 10) { + 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." + ); + } + } } - }); - return { - then: function (resolve, reject) { - didAwaitActCall = true; - thenable.then( - function (returnValue) { - popActScope(prevActQueue, prevActScopeDepth); + } + } - if (prevActScopeDepth === 0) { - // We're exiting the outermost `act` scope. Flush the queue. - try { - flushActQueue(queue); - enqueueTask(function () { - return ( - // Recursively flush tasks scheduled by a microtask. - recursivelyFlushAsyncActWork(returnValue, resolve, reject) - ); - }); - } catch (error) { - // `thenable` might not be a real promise, and `flushActQueue` - // might throw, so we need to wrap `flushActQueue` in a - // try/catch. - reject(error); + var didWarnAboutMessageChannel = false; + var enqueueTaskImpl = null; + function enqueueTask(task) { + if (enqueueTaskImpl === null) { + try { + // read require off the module object to get around the bundlers. + // we don't want them to detect a require and bundle a Node polyfill. + var requireString = ("require" + Math.random()).slice(0, 7); + var nodeRequire = module && module[requireString]; // assuming we're in node, let's try to get node's + // version of setImmediate, bypassing fake timers if any. + + enqueueTaskImpl = nodeRequire.call(module, "timers").setImmediate; + } catch (_err) { + // we're in a browser + // we can't use regular timers because they may still be faked + // so we try MessageChannel+postMessage instead + enqueueTaskImpl = function (callback) { + { + if (didWarnAboutMessageChannel === false) { + didWarnAboutMessageChannel = true; + + if (typeof MessageChannel === "undefined") { + error( + "This browser does not have a MessageChannel implementation, " + + "so enqueuing tasks via await act(async () => ...) will fail. " + + "Please file an issue at https://github.com/facebook/react/issues " + + "if you encounter this warning." + ); } - } else { - resolve(returnValue); } - }, - function (error) { - popActScope(prevActQueue, prevActScopeDepth); - reject(error); } - ); + + var channel = new MessageChannel(); + channel.port1.onmessage = callback; + channel.port2.postMessage(undefined); + }; } - }; - } else { - var returnValue = result; // The callback is not an async function. Exit the current - // scope immediately. + } + + return enqueueTaskImpl(task); + } + + // number of `act` scopes on the stack. - popActScope(prevActQueue, prevActScopeDepth); + var actScopeDepth = 0; // We only warn the first time you neglect to await an async `act` scope. - if (prevActScopeDepth === 0) { - // We're exiting the outermost `act` scope. Flush the queue. - flushActQueue(queue); // If the queue is not empty, it implies that we intentionally yielded - // to the main thread, because something suspended. We will continue - // in an asynchronous task. + var didWarnNoAwaitAct = false; + function act(callback) { + { + // When ReactCurrentActQueue.current is not null, it signals to React that + // we're currently inside an `act` scope. React will push all its tasks to + // this queue instead of scheduling them with platform APIs. + // + // We set this to an empty array when we first enter an `act` scope, and + // only unset it once we've left the outermost `act` scope — remember that + // `act` calls can be nested. // - // Warn if something suspends but the `act` call is not awaited. - // In a future release, consider making this an error. + // If we're already inside an `act` scope, reuse the existing queue. + var prevIsBatchingLegacy = ReactCurrentActQueue.isBatchingLegacy; + var prevActQueue = ReactCurrentActQueue.current; + var prevActScopeDepth = actScopeDepth; + actScopeDepth++; + var queue = (ReactCurrentActQueue.current = + prevActQueue !== null ? prevActQueue : []); // Used to reproduce behavior of `batchedUpdates` in legacy mode. Only + // set to `true` while the given callback is executed, not for updates + // triggered during an async event, because this is how the legacy + // implementation of `act` behaved. + + ReactCurrentActQueue.isBatchingLegacy = true; + var result; // This tracks whether the `act` call is awaited. In certain cases, not + // awaiting it is a mistake, so we will detect that and warn. + + var didAwaitActCall = false; + + try { + // Reset this to `false` right before entering the React work loop. The + // only place we ever read this fields is just below, right after running + // the callback. So we don't need to reset after the callback runs. + ReactCurrentActQueue.didScheduleLegacyUpdate = false; + result = callback(); + var didScheduleLegacyUpdate = + ReactCurrentActQueue.didScheduleLegacyUpdate; // Replicate behavior of original `act` implementation in legacy mode, + // which flushed updates immediately after the scope function exits, even + // if it's an async function. + + if (!prevIsBatchingLegacy && didScheduleLegacyUpdate) { + flushActQueue(queue); + } // `isBatchingLegacy` gets reset using the regular stack, not the async + // one used to track `act` scopes. Why, you may be wondering? Because + // that's how it worked before version 18. Yes, it's confusing! We should + // delete legacy mode!! + + ReactCurrentActQueue.isBatchingLegacy = prevIsBatchingLegacy; + } catch (error) { + // `isBatchingLegacy` gets reset using the regular stack, not the async + // one used to track `act` scopes. Why, you may be wondering? Because + // that's how it worked before version 18. Yes, it's confusing! We should + // delete legacy mode!! + ReactCurrentActQueue.isBatchingLegacy = prevIsBatchingLegacy; + popActScope(prevActQueue, prevActScopeDepth); + throw error; + } + + if ( + result !== null && + typeof result === "object" && // $FlowFixMe[method-unbinding] + typeof result.then === "function" + ) { + // A promise/thenable was returned from the callback. Wait for it to + // resolve before flushing the queue. + // + // If `act` were implemented as an async function, this whole block could + // be a single `await` call. That's really the only difference between + // this branch and the next one. + var thenable = result; // Warn if the an `act` call with an async scope is not awaited. In a + // future release, consider making this an error. - if (queue.length !== 0) { queueSeveralMicrotasks(function () { if (!didAwaitActCall && !didWarnNoAwaitAct) { didWarnNoAwaitAct = true; error( - "A component suspended inside an `act` scope, but the " + - "`act` call was not awaited. When testing React " + - "components that depend on asynchronous data, you must " + - "await the result:\n\n" + - "await act(() => ...)" + "You called act(async () => ...) without await. " + + "This could lead to unexpected testing behaviour, " + + "interleaving multiple act calls and mixing their " + + "scopes. " + + "You should - await act(async () => ...);" ); } }); - } // Like many things in this module, this is next part is confusing. - // - // We do not currently require every `act` call that is passed a - // callback to be awaited, through arguably we should. Since this - // callback was synchronous, we need to exit the current scope before - // returning. - // - // However, if thenable we're about to return *is* awaited, we'll - // immediately restore the current scope. So it shouldn't observable. - // - // This doesn't affect the case where the scope callback is async, - // because we always require those calls to be awaited. - // - // TODO: In a future version, consider always requiring all `act` calls - // to be awaited, regardless of whether the callback is sync or async. - - ReactCurrentActQueue.current = null; - } + return { + then: function (resolve, reject) { + didAwaitActCall = true; + thenable.then( + function (returnValue) { + popActScope(prevActQueue, prevActScopeDepth); + + if (prevActScopeDepth === 0) { + // We're exiting the outermost `act` scope. Flush the queue. + try { + flushActQueue(queue); + enqueueTask(function () { + return ( + // Recursively flush tasks scheduled by a microtask. + recursivelyFlushAsyncActWork( + returnValue, + resolve, + reject + ) + ); + }); + } catch (error) { + // `thenable` might not be a real promise, and `flushActQueue` + // might throw, so we need to wrap `flushActQueue` in a + // try/catch. + reject(error); + } + } else { + resolve(returnValue); + } + }, + function (error) { + popActScope(prevActQueue, prevActScopeDepth); + reject(error); + } + ); + } + }; + } else { + var returnValue = result; // The callback is not an async function. Exit the current + // scope immediately. - return { - then: function (resolve, reject) { - didAwaitActCall = true; + popActScope(prevActQueue, prevActScopeDepth); if (prevActScopeDepth === 0) { - // If the `act` call is awaited, restore the queue we were - // using before (see long comment above) so we can flush it. - ReactCurrentActQueue.current = queue; - enqueueTask(function () { - return ( - // Recursively flush tasks scheduled by a microtask. - recursivelyFlushAsyncActWork(returnValue, resolve, reject) - ); - }); - } else { - resolve(returnValue); + // We're exiting the outermost `act` scope. Flush the queue. + flushActQueue(queue); // If the queue is not empty, it implies that we intentionally yielded + // to the main thread, because something suspended. We will continue + // in an asynchronous task. + // + // Warn if something suspends but the `act` call is not awaited. + // In a future release, consider making this an error. + + if (queue.length !== 0) { + queueSeveralMicrotasks(function () { + if (!didAwaitActCall && !didWarnNoAwaitAct) { + didWarnNoAwaitAct = true; + + error( + "A component suspended inside an `act` scope, but the " + + "`act` call was not awaited. When testing React " + + "components that depend on asynchronous data, you must " + + "await the result:\n\n" + + "await act(() => ...)" + ); + } + }); + } // Like many things in this module, this is next part is confusing. + // + // We do not currently require every `act` call that is passed a + // callback to be awaited, through arguably we should. Since this + // callback was synchronous, we need to exit the current scope before + // returning. + // + // However, if thenable we're about to return *is* awaited, we'll + // immediately restore the current scope. So it shouldn't observable. + // + // This doesn't affect the case where the scope callback is async, + // because we always require those calls to be awaited. + // + // TODO: In a future version, consider always requiring all `act` calls + // to be awaited, regardless of whether the callback is sync or async. + + ReactCurrentActQueue.current = null; } - } - }; - } - } -} - -function popActScope(prevActQueue, prevActScopeDepth) { - { - if (prevActScopeDepth !== actScopeDepth - 1) { - error( - "You seem to have overlapping act() calls, this is not supported. " + - "Be sure to await previous act() calls before making a new one. " - ); - } - - actScopeDepth = prevActScopeDepth; - } -} - -function recursivelyFlushAsyncActWork(returnValue, resolve, reject) { - { - // Check if any tasks were scheduled asynchronously. - var queue = ReactCurrentActQueue.current; - - if (queue !== null) { - if (queue.length !== 0) { - // Async tasks were scheduled, mostly likely in a microtask. - // Keep flushing until there are no more. - try { - flushActQueue(queue); // The work we just performed may have schedule additional async - // tasks. Wait a macrotask and check again. - - enqueueTask(function () { - return recursivelyFlushAsyncActWork(returnValue, resolve, reject); - }); - } catch (error) { - // Leave remaining tasks on the queue if something throws. - reject(error); - } - } else { - // The queue is empty. We can finish. - ReactCurrentActQueue.current = null; - resolve(returnValue); - } - } else { - resolve(returnValue); - } - } -} - -var isFlushing = false; -function flushActQueue(queue) { - { - if (!isFlushing) { - // Prevent re-entrance. - isFlushing = true; - var i = 0; + return { + then: function (resolve, reject) { + didAwaitActCall = true; - try { - for (; i < queue.length; i++) { - var callback = queue[i]; - - do { - ReactCurrentActQueue.didUsePromise = false; - var continuation = callback(false); - - if (continuation !== null) { - if (ReactCurrentActQueue.didUsePromise) { - // The component just suspended. Yield to the main thread in - // case the promise is already resolved. If so, it will ping in - // a microtask and we can resume without unwinding the stack. - queue[i] = callback; - queue.splice(0, i); - return; + if (prevActScopeDepth === 0) { + // If the `act` call is awaited, restore the queue we were + // using before (see long comment above) so we can flush it. + ReactCurrentActQueue.current = queue; + enqueueTask(function () { + return ( + // Recursively flush tasks scheduled by a microtask. + recursivelyFlushAsyncActWork(returnValue, resolve, reject) + ); + }); + } else { + resolve(returnValue); } - - callback = continuation; - } else { - break; } - } while (true); - } // We flushed the entire queue. - - queue.length = 0; - } catch (error) { - // If something throws, leave the remaining callbacks on the queue. - queue.splice(0, i + 1); - throw error; - } finally { - isFlushing = false; - } - } - } -} // Some of our warnings attempt to detect if the `act` call is awaited by -// checking in an asynchronous task. Wait a few microtasks before checking. The -// only reason one isn't sufficient is we want to accommodate the case where an -// `act` call is returned from an async function without first being awaited, -// since that's a somewhat common pattern. If you do this too many times in a -// nested sequence, you might get a warning, but you can always fix by awaiting -// the call. -// -// A macrotask would also work (and is the fallback) but depending on the test -// environment it may cause the warning to fire too late. - -var queueSeveralMicrotasks = - typeof queueMicrotask === "function" - ? function (callback) { - queueMicrotask(function () { - return queueMicrotask(callback); - }); - } - : enqueueTask; - -var createElement = createElementWithValidation; -var cloneElement = cloneElementWithValidation; -var Children = { - map: mapChildren, - forEach: forEachChildren, - count: countChildren, - toArray: toArray, - only: onlyChild -}; - -var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; -var RESERVED_PROPS = { - key: true, - ref: true, - __self: true, - __source: true -}; -var specialPropKeyWarningShown; -var specialPropRefWarningShown; -var didWarnAboutStringRefs; - -{ - didWarnAboutStringRefs = {}; -} - -function hasValidRef(config) { - { - if (hasOwnProperty.call(config, "ref")) { - var getter = Object.getOwnPropertyDescriptor(config, "ref").get; - - if (getter && getter.isReactWarning) { - return false; + }; + } } } - } - - return config.ref !== undefined; -} -function hasValidKey(config) { - { - if (hasOwnProperty.call(config, "key")) { - var getter = Object.getOwnPropertyDescriptor(config, "key").get; + function popActScope(prevActQueue, prevActScopeDepth) { + { + if (prevActScopeDepth !== actScopeDepth - 1) { + error( + "You seem to have overlapping act() calls, this is not supported. " + + "Be sure to await previous act() calls before making a new one. " + ); + } - if (getter && getter.isReactWarning) { - return false; + actScopeDepth = prevActScopeDepth; } } - } - - return config.key !== undefined; -} -function warnIfStringRefCannotBeAutoConverted(config, self) { - { - if ( - typeof config.ref === "string" && - ReactCurrentOwner$1.current && - self && - ReactCurrentOwner$1.current.stateNode !== self - ) { - var componentName = getComponentNameFromType( - ReactCurrentOwner$1.current.type - ); - - if (!didWarnAboutStringRefs[componentName]) { - error( - 'Component "%s" contains the string ref "%s". ' + - "Support for string refs will be removed in a future major release. " + - "This case cannot be automatically converted to an arrow function. " + - "We ask you to manually fix this case by using useRef() or createRef() instead. " + - "Learn more about using refs safely here: " + - "https://reactjs.org/link/strict-mode-string-ref", - getComponentNameFromType(ReactCurrentOwner$1.current.type), - config.ref - ); - - didWarnAboutStringRefs[componentName] = true; + function recursivelyFlushAsyncActWork(returnValue, resolve, reject) { + { + // Check if any tasks were scheduled asynchronously. + var queue = ReactCurrentActQueue.current; + + if (queue !== null) { + if (queue.length !== 0) { + // Async tasks were scheduled, mostly likely in a microtask. + // Keep flushing until there are no more. + try { + flushActQueue(queue); // The work we just performed may have schedule additional async + // tasks. Wait a macrotask and check again. + + enqueueTask(function () { + return recursivelyFlushAsyncActWork( + returnValue, + resolve, + reject + ); + }); + } catch (error) { + // Leave remaining tasks on the queue if something throws. + reject(error); + } + } else { + // The queue is empty. We can finish. + ReactCurrentActQueue.current = null; + resolve(returnValue); + } + } else { + resolve(returnValue); + } } } - } -} -function defineKeyPropWarningGetter(props, displayName) { - { - var warnAboutAccessingKey = function () { - if (!specialPropKeyWarningShown) { - specialPropKeyWarningShown = true; + var isFlushing = false; - error( - "%s: `key` is not a prop. Trying to access it will result " + - "in `undefined` being returned. If you need to access the same " + - "value within the child component, you should pass it as a different " + - "prop. (https://reactjs.org/link/special-props)", - displayName - ); + function flushActQueue(queue) { + { + if (!isFlushing) { + // Prevent re-entrance. + isFlushing = true; + var i = 0; + + try { + for (; i < queue.length; i++) { + var callback = queue[i]; + + do { + ReactCurrentActQueue.didUsePromise = false; + var continuation = callback(false); + + if (continuation !== null) { + if (ReactCurrentActQueue.didUsePromise) { + // The component just suspended. Yield to the main thread in + // case the promise is already resolved. If so, it will ping in + // a microtask and we can resume without unwinding the stack. + queue[i] = callback; + queue.splice(0, i); + return; + } + + callback = continuation; + } else { + break; + } + } while (true); + } // We flushed the entire queue. + + queue.length = 0; + } catch (error) { + // If something throws, leave the remaining callbacks on the queue. + queue.splice(0, i + 1); + throw error; + } finally { + isFlushing = false; + } + } } + } // Some of our warnings attempt to detect if the `act` call is awaited by + // checking in an asynchronous task. Wait a few microtasks before checking. The + // only reason one isn't sufficient is we want to accommodate the case where an + // `act` call is returned from an async function without first being awaited, + // since that's a somewhat common pattern. If you do this too many times in a + // nested sequence, you might get a warning, but you can always fix by awaiting + // the call. + // + // A macrotask would also work (and is the fallback) but depending on the test + // environment it may cause the warning to fire too late. + + var queueSeveralMicrotasks = + typeof queueMicrotask === "function" + ? function (callback) { + queueMicrotask(function () { + return queueMicrotask(callback); + }); + } + : enqueueTask; + + var createElement = createElementWithValidation; + var cloneElement = cloneElementWithValidation; + var Children = { + map: mapChildren, + forEach: forEachChildren, + count: countChildren, + toArray: toArray, + only: onlyChild }; - warnAboutAccessingKey.isReactWarning = true; - Object.defineProperty(props, "key", { - get: warnAboutAccessingKey, - configurable: true - }); - } -} - -function defineRefPropWarningGetter(props, displayName) { - { - var warnAboutAccessingRef = function () { - if (!specialPropRefWarningShown) { - specialPropRefWarningShown = true; - - error( - "%s: `ref` is not a prop. Trying to access it will result " + - "in `undefined` being returned. If you need to access the same " + - "value within the child component, you should pass it as a different " + - "prop. (https://reactjs.org/link/special-props)", - displayName - ); - } + var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; + var RESERVED_PROPS = { + key: true, + ref: true, + __self: true, + __source: true }; + var specialPropKeyWarningShown; + var specialPropRefWarningShown; + var didWarnAboutStringRefs; - warnAboutAccessingRef.isReactWarning = true; - Object.defineProperty(props, "ref", { - get: warnAboutAccessingRef, - configurable: true - }); - } -} -/** - * Factory method to create a new React element. This no longer adheres to - * the class pattern, so do not use new to call it. Also, instanceof check - * will not work. Instead test $$typeof field against Symbol.for('react.element') to check - * if something is a React Element. - * - * @param {*} type - * @param {*} props - * @param {*} key - * @param {string|object} ref - * @param {*} owner - * @param {*} self A *temporary* helper to detect places where `this` is - * different from the `owner` when React.createElement is called, so that we - * can warn. We want to get rid of owner and replace string `ref`s with arrow - * functions, and as long as `this` and owner are the same, there will be no - * change in behavior. - * @param {*} source An annotation object (added by a transpiler or otherwise) - * indicating filename, line number, and/or other information. - * @internal - */ + { + didWarnAboutStringRefs = {}; + } -function ReactElement(type, key, ref, self, source, owner, props) { - var element = { - // This tag allows us to uniquely identify this as a React Element - $$typeof: REACT_ELEMENT_TYPE, - // Built-in properties that belong on the element - type: type, - key: key, - ref: ref, - props: props, - // Record the component responsible for creating this element. - _owner: owner - }; - - { - // The validation flag is currently mutative. We put it on - // an external backing store so that we can freeze the whole object. - // This can be replaced with a WeakMap once they are implemented in - // commonly used development environments. - element._store = {}; // To make comparing ReactElements easier for testing purposes, we make - // the validation flag non-enumerable (where possible, which should - // include every environment we run tests in), so the test framework - // ignores it. - - Object.defineProperty(element._store, "validated", { - configurable: false, - enumerable: false, - writable: true, - value: false - }); // self and source are DEV only properties. - - Object.defineProperty(element, "_self", { - configurable: false, - enumerable: false, - writable: false, - value: self - }); // Two elements created in two different places should be considered - // equal for testing purposes and therefore we hide it from enumeration. - - Object.defineProperty(element, "_source", { - configurable: false, - enumerable: false, - writable: false, - value: source - }); - - if (Object.freeze) { - Object.freeze(element.props); - Object.freeze(element); - } - } - - return element; -} -/** - * https://github.com/reactjs/rfcs/pull/107 - * @param {*} type - * @param {object} props - * @param {string} key - */ + function hasValidRef(config) { + { + if (hasOwnProperty.call(config, "ref")) { + var getter = Object.getOwnPropertyDescriptor(config, "ref").get; -function jsxDEV$1(type, config, maybeKey, source, self) { - { - var propName; // Reserved names are extracted + if (getter && getter.isReactWarning) { + return false; + } + } + } - var props = {}; - var key = null; - var ref = null; // Currently, key can be spread in as a prop. This causes a potential - // issue if key is also explicitly declared (ie.
- // or
). We want to deprecate key spread, - // but as an intermediary step, we will use jsxDEV for everything except - //
, because we aren't currently able to tell if - // key is explicitly declared to be undefined or not. + return config.ref !== undefined; + } - if (maybeKey !== undefined) { + function hasValidKey(config) { { - checkKeyStringCoercion(maybeKey); + if (hasOwnProperty.call(config, "key")) { + var getter = Object.getOwnPropertyDescriptor(config, "key").get; + + if (getter && getter.isReactWarning) { + return false; + } + } } - key = "" + maybeKey; + return config.key !== undefined; } - if (hasValidKey(config)) { + function warnIfStringRefCannotBeAutoConverted(config, self) { { - checkKeyStringCoercion(config.key); - } + if ( + typeof config.ref === "string" && + ReactCurrentOwner$1.current && + self && + ReactCurrentOwner$1.current.stateNode !== self + ) { + var componentName = getComponentNameFromType( + ReactCurrentOwner$1.current.type + ); + + if (!didWarnAboutStringRefs[componentName]) { + error( + 'Component "%s" contains the string ref "%s". ' + + "Support for string refs will be removed in a future major release. " + + "This case cannot be automatically converted to an arrow function. " + + "We ask you to manually fix this case by using useRef() or createRef() instead. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-string-ref", + getComponentNameFromType(ReactCurrentOwner$1.current.type), + config.ref + ); - key = "" + config.key; + didWarnAboutStringRefs[componentName] = true; + } + } + } } - if (hasValidRef(config)) { - ref = config.ref; - warnIfStringRefCannotBeAutoConverted(config, self); - } // Remaining properties are added to a new props object + function defineKeyPropWarningGetter(props, displayName) { + { + var warnAboutAccessingKey = function () { + if (!specialPropKeyWarningShown) { + specialPropKeyWarningShown = true; - for (propName in config) { - if ( - hasOwnProperty.call(config, propName) && - !RESERVED_PROPS.hasOwnProperty(propName) - ) { - props[propName] = config[propName]; + error( + "%s: `key` is not a prop. Trying to access it will result " + + "in `undefined` being returned. If you need to access the same " + + "value within the child component, you should pass it as a different " + + "prop. (https://reactjs.org/link/special-props)", + displayName + ); + } + }; + + warnAboutAccessingKey.isReactWarning = true; + Object.defineProperty(props, "key", { + get: warnAboutAccessingKey, + configurable: true + }); } - } // Resolve default props + } - if (type && type.defaultProps) { - var defaultProps = type.defaultProps; + function defineRefPropWarningGetter(props, displayName) { + { + var warnAboutAccessingRef = function () { + if (!specialPropRefWarningShown) { + specialPropRefWarningShown = true; - for (propName in defaultProps) { - if (props[propName] === undefined) { - props[propName] = defaultProps[propName]; - } + error( + "%s: `ref` is not a prop. Trying to access it will result " + + "in `undefined` being returned. If you need to access the same " + + "value within the child component, you should pass it as a different " + + "prop. (https://reactjs.org/link/special-props)", + displayName + ); + } + }; + + warnAboutAccessingRef.isReactWarning = true; + Object.defineProperty(props, "ref", { + get: warnAboutAccessingRef, + configurable: true + }); } } + /** + * Factory method to create a new React element. This no longer adheres to + * the class pattern, so do not use new to call it. Also, instanceof check + * will not work. Instead test $$typeof field against Symbol.for('react.element') to check + * if something is a React Element. + * + * @param {*} type + * @param {*} props + * @param {*} key + * @param {string|object} ref + * @param {*} owner + * @param {*} self A *temporary* helper to detect places where `this` is + * different from the `owner` when React.createElement is called, so that we + * can warn. We want to get rid of owner and replace string `ref`s with arrow + * functions, and as long as `this` and owner are the same, there will be no + * change in behavior. + * @param {*} source An annotation object (added by a transpiler or otherwise) + * indicating filename, line number, and/or other information. + * @internal + */ + + function ReactElement(type, key, ref, self, source, owner, props) { + var element = { + // This tag allows us to uniquely identify this as a React Element + $$typeof: REACT_ELEMENT_TYPE, + // Built-in properties that belong on the element + type: type, + key: key, + ref: ref, + props: props, + // Record the component responsible for creating this element. + _owner: owner + }; - if (key || ref) { - var displayName = - typeof type === "function" - ? type.displayName || type.name || "Unknown" - : type; + { + // The validation flag is currently mutative. We put it on + // an external backing store so that we can freeze the whole object. + // This can be replaced with a WeakMap once they are implemented in + // commonly used development environments. + element._store = {}; // To make comparing ReactElements easier for testing purposes, we make + // the validation flag non-enumerable (where possible, which should + // include every environment we run tests in), so the test framework + // ignores it. + + Object.defineProperty(element._store, "validated", { + configurable: false, + enumerable: false, + writable: true, + value: false + }); // self and source are DEV only properties. + + Object.defineProperty(element, "_self", { + configurable: false, + enumerable: false, + writable: false, + value: self + }); // Two elements created in two different places should be considered + // equal for testing purposes and therefore we hide it from enumeration. + + Object.defineProperty(element, "_source", { + configurable: false, + enumerable: false, + writable: false, + value: source + }); - if (key) { - defineKeyPropWarningGetter(props, displayName); + if (Object.freeze) { + Object.freeze(element.props); + Object.freeze(element); + } } - if (ref) { - defineRefPropWarningGetter(props, displayName); - } + return element; } + /** + * https://github.com/reactjs/rfcs/pull/107 + * @param {*} type + * @param {object} props + * @param {string} key + */ + + function jsxDEV$1(type, config, maybeKey, source, self) { + { + var propName; // Reserved names are extracted + + var props = {}; + var key = null; + var ref = null; // Currently, key can be spread in as a prop. This causes a potential + // issue if key is also explicitly declared (ie.
+ // or
). We want to deprecate key spread, + // but as an intermediary step, we will use jsxDEV for everything except + //
, because we aren't currently able to tell if + // key is explicitly declared to be undefined or not. + + if (maybeKey !== undefined) { + { + checkKeyStringCoercion(maybeKey); + } - return ReactElement( - type, - key, - ref, - self, - source, - ReactCurrentOwner$1.current, - props - ); - } -} + key = "" + maybeKey; + } -var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; -var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; -var REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"); + if (hasValidKey(config)) { + { + checkKeyStringCoercion(config.key); + } -function setCurrentlyValidatingElement(element) { - { - if (element) { - var owner = element._owner; - var stack = describeUnknownElementTypeFrameInDEV( - element.type, - element._source, - owner ? owner.type : null - ); - ReactDebugCurrentFrame.setExtraStackFrame(stack); - } else { - ReactDebugCurrentFrame.setExtraStackFrame(null); - } - } -} + key = "" + config.key; + } -var propTypesMisspellWarningShown; + if (hasValidRef(config)) { + ref = config.ref; + warnIfStringRefCannotBeAutoConverted(config, self); + } // Remaining properties are added to a new props object + + for (propName in config) { + if ( + hasOwnProperty.call(config, propName) && + !RESERVED_PROPS.hasOwnProperty(propName) + ) { + props[propName] = config[propName]; + } + } // Resolve default props -{ - propTypesMisspellWarningShown = false; -} -/** - * Verifies the object is a ReactElement. - * See https://reactjs.org/docs/react-api.html#isvalidelement - * @param {?object} object - * @return {boolean} True if `object` is a ReactElement. - * @final - */ + if (type && type.defaultProps) { + var defaultProps = type.defaultProps; -function isValidElement(object) { - { - return ( - typeof object === "object" && - object !== null && - object.$$typeof === REACT_ELEMENT_TYPE - ); - } -} + for (propName in defaultProps) { + if (props[propName] === undefined) { + props[propName] = defaultProps[propName]; + } + } + } + + if (key || ref) { + var displayName = + typeof type === "function" + ? type.displayName || type.name || "Unknown" + : type; + + if (key) { + defineKeyPropWarningGetter(props, displayName); + } -function getDeclarationErrorAddendum() { - { - if (ReactCurrentOwner.current) { - var name = getComponentNameFromType(ReactCurrentOwner.current.type); + if (ref) { + defineRefPropWarningGetter(props, displayName); + } + } - if (name) { - return "\n\nCheck the render method of `" + name + "`."; + return ReactElement( + type, + key, + ref, + self, + source, + ReactCurrentOwner$1.current, + props + ); } } - return ""; - } -} + var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + var REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"); -function getSourceInfoErrorAddendum(source) { - { - if (source !== undefined) { - var fileName = source.fileName.replace(/^.*[\\\/]/, ""); - var lineNumber = source.lineNumber; - return "\n\nCheck your code at " + fileName + ":" + lineNumber + "."; + function setCurrentlyValidatingElement(element) { + { + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV( + element.type, + element._source, + owner ? owner.type : null + ); + ReactDebugCurrentFrame.setExtraStackFrame(stack); + } else { + ReactDebugCurrentFrame.setExtraStackFrame(null); + } + } } - return ""; - } -} -/** - * Warn if there's no key explicitly set on dynamic arrays of children or - * object keys are not valid. This allows us to keep track of children between - * updates. - */ + var propTypesMisspellWarningShown; -var ownerHasKeyUseWarning = {}; + { + propTypesMisspellWarningShown = false; + } + /** + * Verifies the object is a ReactElement. + * See https://reactjs.org/docs/react-api.html#isvalidelement + * @param {?object} object + * @return {boolean} True if `object` is a ReactElement. + * @final + */ + + function isValidElement(object) { + { + return ( + typeof object === "object" && + object !== null && + object.$$typeof === REACT_ELEMENT_TYPE + ); + } + } -function getCurrentComponentErrorInfo(parentType) { - { - var info = getDeclarationErrorAddendum(); + function getDeclarationErrorAddendum() { + { + if (ReactCurrentOwner.current) { + var name = getComponentNameFromType(ReactCurrentOwner.current.type); - if (!info) { - var parentName = - typeof parentType === "string" - ? parentType - : parentType.displayName || parentType.name; + if (name) { + return "\n\nCheck the render method of `" + name + "`."; + } + } - if (parentName) { - info = - "\n\nCheck the top-level render call using <" + parentName + ">."; + return ""; } } - return info; - } -} -/** - * Warn if the element doesn't have an explicit key assigned to it. - * This element is in an array. The array could grow and shrink or be - * reordered. All children that haven't already been validated are required to - * have a "key" property assigned to it. Error statuses are cached so a warning - * will only be shown once. - * - * @internal - * @param {ReactElement} element Element that requires a key. - * @param {*} parentType element's parent's type. - */ + function getSourceInfoErrorAddendum(source) { + { + if (source !== undefined) { + var fileName = source.fileName.replace(/^.*[\\\/]/, ""); + var lineNumber = source.lineNumber; + return "\n\nCheck your code at " + fileName + ":" + lineNumber + "."; + } -function validateExplicitKey(element, parentType) { - { - if (!element._store || element._store.validated || element.key != null) { - return; + return ""; + } } + /** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ - element._store.validated = true; - var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType); + var ownerHasKeyUseWarning = {}; - if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { - return; - } + function getCurrentComponentErrorInfo(parentType) { + { + var info = getDeclarationErrorAddendum(); - ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a - // property, it may be the creator of the child that's responsible for - // assigning it a key. + if (!info) { + var parentName = + typeof parentType === "string" + ? parentType + : parentType.displayName || parentType.name; - var childOwner = ""; + if (parentName) { + info = + "\n\nCheck the top-level render call using <" + parentName + ">."; + } + } - if ( - element && - element._owner && - element._owner !== ReactCurrentOwner.current - ) { - // Give the component that originally created this child. - childOwner = - " It was passed a child from " + - getComponentNameFromType(element._owner.type) + - "."; + return info; + } } + /** + * Warn if the element doesn't have an explicit key assigned to it. + * This element is in an array. The array could grow and shrink or be + * reordered. All children that haven't already been validated are required to + * have a "key" property assigned to it. Error statuses are cached so a warning + * will only be shown once. + * + * @internal + * @param {ReactElement} element Element that requires a key. + * @param {*} parentType element's parent's type. + */ + + function validateExplicitKey(element, parentType) { + { + if ( + !element._store || + element._store.validated || + element.key != null + ) { + return; + } - setCurrentlyValidatingElement(element); - - error( - 'Each child in a list should have a unique "key" prop.' + - "%s%s See https://reactjs.org/link/warning-keys for more information.", - currentComponentErrorInfo, - childOwner - ); + element._store.validated = true; + var currentComponentErrorInfo = + getCurrentComponentErrorInfo(parentType); - setCurrentlyValidatingElement(null); - } -} -/** - * Ensure that every element either is passed in a static location, in an - * array with an explicit keys property defined, or in an object literal - * with valid key property. - * - * @internal - * @param {ReactNode} node Statically passed child of any type. - * @param {*} parentType node's parent's type. - */ + if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { + return; + } -function validateChildKeys(node, parentType) { - { - if (typeof node !== "object" || !node) { - return; - } + ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a + // property, it may be the creator of the child that's responsible for + // assigning it a key. - if (node.$$typeof === REACT_CLIENT_REFERENCE); - else if (isArray(node)) { - for (var i = 0; i < node.length; i++) { - var child = node[i]; + var childOwner = ""; - if (isValidElement(child)) { - validateExplicitKey(child, parentType); + if ( + element && + element._owner && + element._owner !== ReactCurrentOwner.current + ) { + // Give the component that originally created this child. + childOwner = + " It was passed a child from " + + getComponentNameFromType(element._owner.type) + + "."; } + + setCurrentlyValidatingElement(element); + + error( + 'Each child in a list should have a unique "key" prop.' + + "%s%s See https://reactjs.org/link/warning-keys for more information.", + currentComponentErrorInfo, + childOwner + ); + + setCurrentlyValidatingElement(null); } - } else if (isValidElement(node)) { - // This element was passed in a valid location. - if (node._store) { - node._store.validated = true; - } - } else { - var iteratorFn = getIteratorFn(node); + } + /** + * Ensure that every element either is passed in a static location, in an + * array with an explicit keys property defined, or in an object literal + * with valid key property. + * + * @internal + * @param {ReactNode} node Statically passed child of any type. + * @param {*} parentType node's parent's type. + */ + + function validateChildKeys(node, parentType) { + { + if (typeof node !== "object" || !node) { + return; + } - if (typeof iteratorFn === "function") { - // Entry iterators used to provide implicit keys, - // but now we print a separate warning for them later. - if (iteratorFn !== node.entries) { - var iterator = iteratorFn.call(node); - var step; + if (node.$$typeof === REACT_CLIENT_REFERENCE); + else if (isArray(node)) { + for (var i = 0; i < node.length; i++) { + var child = node[i]; - while (!(step = iterator.next()).done) { - if (isValidElement(step.value)) { - validateExplicitKey(step.value, parentType); + if (isValidElement(child)) { + validateExplicitKey(child, parentType); + } + } + } else if (isValidElement(node)) { + // This element was passed in a valid location. + if (node._store) { + node._store.validated = true; + } + } else { + var iteratorFn = getIteratorFn(node); + + if (typeof iteratorFn === "function") { + // Entry iterators used to provide implicit keys, + // but now we print a separate warning for them later. + if (iteratorFn !== node.entries) { + var iterator = iteratorFn.call(node); + var step; + + while (!(step = iterator.next()).done) { + if (isValidElement(step.value)) { + validateExplicitKey(step.value, parentType); + } + } } } } } } - } -} -/** - * Given an element, validate that its props follow the propTypes definition, - * provided by the type. - * - * @param {ReactElement} element - */ - -function validatePropTypes(element) { - { - var type = element.type; + /** + * Given an element, validate that its props follow the propTypes definition, + * provided by the type. + * + * @param {ReactElement} element + */ + + function validatePropTypes(element) { + { + var type = element.type; - if (type === null || type === undefined || typeof type === "string") { - return; - } + if (type === null || type === undefined || typeof type === "string") { + return; + } - if (type.$$typeof === REACT_CLIENT_REFERENCE) { - return; - } + if (type.$$typeof === REACT_CLIENT_REFERENCE) { + return; + } - var propTypes; + var propTypes; - if (typeof type === "function") { - propTypes = type.propTypes; - } else if ( - typeof type === "object" && - (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here. - // Inner props are checked in the reconciler. - type.$$typeof === REACT_MEMO_TYPE) - ) { - propTypes = type.propTypes; - } else { - return; - } + if (typeof type === "function") { + propTypes = type.propTypes; + } else if ( + typeof type === "object" && + (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here. + // Inner props are checked in the reconciler. + type.$$typeof === REACT_MEMO_TYPE) + ) { + propTypes = type.propTypes; + } else { + return; + } - if (propTypes) { - // Intentionally inside to avoid triggering lazy initializers: - var name = getComponentNameFromType(type); - checkPropTypes(propTypes, element.props, "prop", name, element); - } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) { - propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers: + if (propTypes) { + // Intentionally inside to avoid triggering lazy initializers: + var name = getComponentNameFromType(type); + checkPropTypes(propTypes, element.props, "prop", name, element); + } else if ( + type.PropTypes !== undefined && + !propTypesMisspellWarningShown + ) { + propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers: - var _name = getComponentNameFromType(type); + var _name = getComponentNameFromType(type); - error( - "Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?", - _name || "Unknown" - ); - } + error( + "Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?", + _name || "Unknown" + ); + } - if ( - typeof type.getDefaultProps === "function" && - !type.getDefaultProps.isReactClassApproved - ) { - error( - "getDefaultProps is only used on classic React.createClass " + - "definitions. Use a static property named `defaultProps` instead." - ); + if ( + typeof type.getDefaultProps === "function" && + !type.getDefaultProps.isReactClassApproved + ) { + error( + "getDefaultProps is only used on classic React.createClass " + + "definitions. Use a static property named `defaultProps` instead." + ); + } + } } - } -} -/** - * Given a fragment, validate that it can only be provided with fragment props - * @param {ReactElement} fragment - */ + /** + * Given a fragment, validate that it can only be provided with fragment props + * @param {ReactElement} fragment + */ -function validateFragmentProps(fragment) { - { - var keys = Object.keys(fragment.props); + function validateFragmentProps(fragment) { + { + var keys = Object.keys(fragment.props); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; - if (key !== "children" && key !== "key") { - setCurrentlyValidatingElement(fragment); + if (key !== "children" && key !== "key") { + setCurrentlyValidatingElement(fragment); - error( - "Invalid prop `%s` supplied to `React.Fragment`. " + - "React.Fragment can only have `key` and `children` props.", - key - ); + error( + "Invalid prop `%s` supplied to `React.Fragment`. " + + "React.Fragment can only have `key` and `children` props.", + key + ); - setCurrentlyValidatingElement(null); - break; - } - } + setCurrentlyValidatingElement(null); + break; + } + } - if (fragment.ref !== null) { - setCurrentlyValidatingElement(fragment); + if (fragment.ref !== null) { + setCurrentlyValidatingElement(fragment); - error("Invalid attribute `ref` supplied to `React.Fragment`."); + error("Invalid attribute `ref` supplied to `React.Fragment`."); - setCurrentlyValidatingElement(null); + setCurrentlyValidatingElement(null); + } + } } - } -} -var didWarnAboutKeySpread = {}; -function jsxWithValidation(type, props, key, isStaticChildren, source, self) { - { - var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to - // succeed and there will likely be errors in render. - - if (!validType) { - var info = ""; + var didWarnAboutKeySpread = {}; + function jsxWithValidation( + type, + props, + key, + isStaticChildren, + source, + self + ) { + { + var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to + // succeed and there will likely be errors in render. + + if (!validType) { + var info = ""; + + if ( + type === undefined || + (typeof type === "object" && + type !== null && + Object.keys(type).length === 0) + ) { + 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."; + } - if ( - type === undefined || - (typeof type === "object" && - type !== null && - Object.keys(type).length === 0) - ) { - 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."; - } + var sourceInfo = getSourceInfoErrorAddendum(source); - var sourceInfo = getSourceInfoErrorAddendum(source); + if (sourceInfo) { + info += sourceInfo; + } else { + info += getDeclarationErrorAddendum(); + } - if (sourceInfo) { - info += sourceInfo; - } else { - info += getDeclarationErrorAddendum(); - } + var typeString; + + if (type === null) { + typeString = "null"; + } else if (isArray(type)) { + typeString = "array"; + } else if ( + type !== undefined && + type.$$typeof === REACT_ELEMENT_TYPE + ) { + typeString = + "<" + (getComponentNameFromType(type.type) || "Unknown") + " />"; + info = + " Did you accidentally export a JSX literal instead of a component?"; + } else { + typeString = typeof type; + } - var typeString; + error( + "React.jsx: type is invalid -- expected a string (for " + + "built-in components) or a class/function (for composite " + + "components) but got: %s.%s", + typeString, + info + ); + } - if (type === null) { - typeString = "null"; - } else if (isArray(type)) { - typeString = "array"; - } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) { - typeString = - "<" + (getComponentNameFromType(type.type) || "Unknown") + " />"; - info = - " Did you accidentally export a JSX literal instead of a component?"; - } else { - typeString = typeof type; - } + var element = jsxDEV$1(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used. + // TODO: Drop this when these are no longer allowed as the type argument. + + if (element == null) { + return element; + } // Skip key warning if the type isn't valid since our key validation logic + // doesn't expect a non-string/function type and can throw confusing errors. + // We don't want exception behavior to differ between dev and prod. + // (Rendering will throw with a helpful message and as soon as the type is + // fixed, the key warnings will appear.) + + if (validType) { + var children = props.children; + + if (children !== undefined) { + if (isStaticChildren) { + if (isArray(children)) { + for (var i = 0; i < children.length; i++) { + validateChildKeys(children[i], type); + } - error( - "React.jsx: type is invalid -- expected a string (for " + - "built-in components) or a class/function (for composite " + - "components) but got: %s.%s", - typeString, - info - ); - } + if (Object.freeze) { + Object.freeze(children); + } + } else { + error( + "React.jsx: Static children should always be an array. " + + "You are likely explicitly calling React.jsxs or React.jsxDEV. " + + "Use the Babel transform instead." + ); + } + } else { + validateChildKeys(children, type); + } + } + } - var element = jsxDEV$1(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used. - // TODO: Drop this when these are no longer allowed as the type argument. + if (hasOwnProperty.call(props, "key")) { + var componentName = getComponentNameFromType(type); + var keys = Object.keys(props).filter(function (k) { + return k !== "key"; + }); + var beforeExample = + keys.length > 0 + ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" + : "{key: someKey}"; - if (element == null) { - return element; - } // Skip key warning if the type isn't valid since our key validation logic - // doesn't expect a non-string/function type and can throw confusing errors. - // We don't want exception behavior to differ between dev and prod. - // (Rendering will throw with a helpful message and as soon as the type is - // fixed, the key warnings will appear.) - - if (validType) { - var children = props.children; - - if (children !== undefined) { - if (isStaticChildren) { - if (isArray(children)) { - for (var i = 0; i < children.length; i++) { - validateChildKeys(children[i], type); - } + if (!didWarnAboutKeySpread[componentName + beforeExample]) { + var afterExample = + keys.length > 0 ? "{" + keys.join(": ..., ") + ": ...}" : "{}"; - if (Object.freeze) { - Object.freeze(children); - } - } else { error( - "React.jsx: Static children should always be an array. " + - "You are likely explicitly calling React.jsxs or React.jsxDEV. " + - "Use the Babel transform instead." + 'A props object containing a "key" prop is being spread into JSX:\n' + + " let props = %s;\n" + + " <%s {...props} />\n" + + "React keys must be passed directly to JSX without using spread:\n" + + " let props = %s;\n" + + " <%s key={someKey} {...props} />", + beforeExample, + componentName, + afterExample, + componentName ); + + didWarnAboutKeySpread[componentName + beforeExample] = true; } - } else { - validateChildKeys(children, type); } - } - } - if (hasOwnProperty.call(props, "key")) { - var componentName = getComponentNameFromType(type); - var keys = Object.keys(props).filter(function (k) { - return k !== "key"; - }); - var beforeExample = - keys.length > 0 - ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" - : "{key: someKey}"; - - if (!didWarnAboutKeySpread[componentName + beforeExample]) { - var afterExample = - keys.length > 0 ? "{" + keys.join(": ..., ") + ": ...}" : "{}"; + if (type === REACT_FRAGMENT_TYPE) { + validateFragmentProps(element); + } else { + validatePropTypes(element); + } - error( - 'A props object containing a "key" prop is being spread into JSX:\n' + - " let props = %s;\n" + - " <%s {...props} />\n" + - "React keys must be passed directly to JSX without using spread:\n" + - " let props = %s;\n" + - " <%s key={someKey} {...props} />", - beforeExample, - componentName, - afterExample, - componentName - ); + return element; + } + } // These two functions exist to still get child warnings in dev + // even with the prod transform. This means that jsxDEV is purely + // opt-in behavior for better messages but that we won't stop + // giving you warnings if you use production apis. - didWarnAboutKeySpread[componentName + beforeExample] = true; + function jsxWithValidationStatic(type, props, key) { + { + return jsxWithValidation(type, props, key, true); } } - - if (type === REACT_FRAGMENT_TYPE) { - validateFragmentProps(element); - } else { - validatePropTypes(element); + function jsxWithValidationDynamic(type, props, key) { + { + return jsxWithValidation(type, props, key, false); + } } - return element; - } -} // These two functions exist to still get child warnings in dev -// even with the prod transform. This means that jsxDEV is purely -// opt-in behavior for better messages but that we won't stop -// giving you warnings if you use production apis. - -function jsxWithValidationStatic(type, props, key) { - { - return jsxWithValidation(type, props, key, true); - } -} -function jsxWithValidationDynamic(type, props, key) { - { - return jsxWithValidation(type, props, key, false); - } -} - -var jsx = jsxWithValidationDynamic; // we may want to special case jsxs internally to take advantage of static children. -// for now we can ship identical prod functions - -var jsxs = jsxWithValidationStatic; -var jsxDEV = jsxWithValidation; - -exports.Children = Children; -exports.Component = Component; -exports.Fragment = REACT_FRAGMENT_TYPE; -exports.Profiler = REACT_PROFILER_TYPE; -exports.PureComponent = PureComponent; -exports.StrictMode = REACT_STRICT_MODE_TYPE; -exports.Suspense = REACT_SUSPENSE_TYPE; -exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = - ReactSharedInternals; -exports.cache = cache; -exports.cloneElement = cloneElement; -exports.createContext = createContext; -exports.createElement = createElement; -exports.createRef = createRef; -exports.experimental_useEffectEvent = useEffectEvent; -exports.forwardRef = forwardRef; -exports.isValidElement = isValidElement$1; -exports.jsx = jsx; -exports.jsxDEV = jsxDEV; -exports.jsxs = jsxs; -exports.lazy = lazy; -exports.memo = memo; -exports.startTransition = startTransition; -exports.unstable_Activity = REACT_OFFSCREEN_TYPE; -exports.unstable_Cache = REACT_CACHE_TYPE; -exports.unstable_DebugTracingMode = REACT_DEBUG_TRACING_MODE_TYPE; -exports.unstable_LegacyHidden = REACT_LEGACY_HIDDEN_TYPE; -exports.unstable_Scope = REACT_SCOPE_TYPE; -exports.unstable_SuspenseList = REACT_SUSPENSE_LIST_TYPE; -exports.unstable_act = act; -exports.unstable_getCacheForType = getCacheForType; -exports.unstable_getCacheSignal = getCacheSignal; -exports.unstable_useCacheRefresh = useCacheRefresh; -exports.unstable_useMemoCache = useMemoCache; -exports.use = use; -exports.useCallback = useCallback; -exports.useContext = useContext; -exports.useDebugValue = useDebugValue; -exports.useDeferredValue = useDeferredValue; -exports.useEffect = useEffect; -exports.useId = useId; -exports.useImperativeHandle = useImperativeHandle; -exports.useInsertionEffect = useInsertionEffect; -exports.useLayoutEffect = useLayoutEffect; -exports.useMemo = useMemo; -exports.useOptimistic = useOptimistic; -exports.useReducer = useReducer; -exports.useRef = useRef; -exports.useState = useState; -exports.useSyncExternalStore = useSyncExternalStore; -exports.useTransition = useTransition; -exports.version = ReactVersion; - - /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ -if ( - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop === - 'function' -) { - __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error()); -} - + var jsx = jsxWithValidationDynamic; // we may want to special case jsxs internally to take advantage of static children. + // for now we can ship identical prod functions + + var jsxs = jsxWithValidationStatic; + var jsxDEV = jsxWithValidation; + + exports.Children = Children; + exports.Component = Component; + exports.Fragment = REACT_FRAGMENT_TYPE; + exports.Profiler = REACT_PROFILER_TYPE; + exports.PureComponent = PureComponent; + exports.StrictMode = REACT_STRICT_MODE_TYPE; + exports.Suspense = REACT_SUSPENSE_TYPE; + exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = + ReactSharedInternals; + exports.cache = cache; + exports.cloneElement = cloneElement; + exports.createContext = createContext; + exports.createElement = createElement; + exports.createRef = createRef; + exports.experimental_useEffectEvent = useEffectEvent; + exports.forwardRef = forwardRef; + exports.isValidElement = isValidElement$1; + exports.jsx = jsx; + exports.jsxDEV = jsxDEV; + exports.jsxs = jsxs; + exports.lazy = lazy; + exports.memo = memo; + exports.startTransition = startTransition; + exports.unstable_Activity = REACT_OFFSCREEN_TYPE; + exports.unstable_Cache = REACT_CACHE_TYPE; + exports.unstable_DebugTracingMode = REACT_DEBUG_TRACING_MODE_TYPE; + exports.unstable_LegacyHidden = REACT_LEGACY_HIDDEN_TYPE; + exports.unstable_Scope = REACT_SCOPE_TYPE; + exports.unstable_SuspenseList = REACT_SUSPENSE_LIST_TYPE; + exports.unstable_act = act; + exports.unstable_getCacheForType = getCacheForType; + exports.unstable_getCacheSignal = getCacheSignal; + exports.unstable_useCacheRefresh = useCacheRefresh; + exports.unstable_useMemoCache = useMemoCache; + exports.use = use; + exports.useCallback = useCallback; + exports.useContext = useContext; + exports.useDebugValue = useDebugValue; + exports.useDeferredValue = useDeferredValue; + exports.useEffect = useEffect; + exports.useId = useId; + exports.useImperativeHandle = useImperativeHandle; + exports.useInsertionEffect = useInsertionEffect; + exports.useLayoutEffect = useLayoutEffect; + exports.useMemo = useMemo; + exports.useOptimistic = useOptimistic; + exports.useReducer = useReducer; + exports.useRef = useRef; + exports.useState = useState; + exports.useSyncExternalStore = useSyncExternalStore; + exports.useTransition = useTransition; + exports.version = ReactVersion; + /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ + if ( + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined" && + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop === + "function" + ) { + __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error()); + } })(); } diff --git a/compiled/facebook-www/React-prod.classic.js b/compiled/facebook-www/React-prod.classic.js index 6933b76933a07..a52c315ebc98f 100644 --- a/compiled/facebook-www/React-prod.classic.js +++ b/compiled/facebook-www/React-prod.classic.js @@ -1,15 +1,15 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @noflow - * @nolint - * @preventMunge - * @preserve-invariant-messages - */ +/* + Copyright (c) Meta Platforms, Inc. and affiliates. + + This source code is licensed under the MIT license found in the + LICENSE file in the root directory of this source tree. + + @noflow + @nolint + @preventMunge + @preserve-invariant-messages +*/ "use strict"; var REACT_ELEMENT_TYPE = Symbol.for("react.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), @@ -587,4 +587,4 @@ exports.useSyncExternalStore = function ( exports.useTransition = function () { return ReactCurrentDispatcher.current.useTransition(); }; -exports.version = "18.3.0-www-classic-685ed7fa"; +exports.version = "18.3.0-www-classic-4b8ff8ef"; diff --git a/compiled/facebook-www/React-prod.modern.js b/compiled/facebook-www/React-prod.modern.js index ca5d0e8e14236..3366039b389c3 100644 --- a/compiled/facebook-www/React-prod.modern.js +++ b/compiled/facebook-www/React-prod.modern.js @@ -1,15 +1,15 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @noflow - * @nolint - * @preventMunge - * @preserve-invariant-messages - */ +/* + Copyright (c) Meta Platforms, Inc. and affiliates. + + This source code is licensed under the MIT license found in the + LICENSE file in the root directory of this source tree. + + @noflow + @nolint + @preventMunge + @preserve-invariant-messages +*/ "use strict"; var REACT_ELEMENT_TYPE = Symbol.for("react.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), @@ -579,4 +579,4 @@ exports.useSyncExternalStore = function ( exports.useTransition = function () { return ReactCurrentDispatcher.current.useTransition(); }; -exports.version = "18.3.0-www-modern-e23232b7"; +exports.version = "18.3.0-www-modern-a539e318"; diff --git a/compiled/facebook-www/React-profiling.classic.js b/compiled/facebook-www/React-profiling.classic.js index 68a5948cbbd75..b921e857184d3 100644 --- a/compiled/facebook-www/React-profiling.classic.js +++ b/compiled/facebook-www/React-profiling.classic.js @@ -1,27 +1,20 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @noflow - * @nolint - * @preventMunge - * @preserve-invariant-messages - */ +/* + Copyright (c) Meta Platforms, Inc. and affiliates. - 'use strict'; + This source code is licensed under the MIT license found in the + LICENSE file in the root directory of this source tree. -/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ -if ( - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart === - 'function' -) { - __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); -} - "use strict"; + @noflow + @nolint + @preventMunge + @preserve-invariant-messages +*/ +"use strict"; +"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && + "function" === + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && + __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error()); var REACT_ELEMENT_TYPE = Symbol.for("react.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), @@ -598,14 +591,8 @@ exports.useSyncExternalStore = function ( exports.useTransition = function () { return ReactCurrentDispatcher.current.useTransition(); }; -exports.version = "18.3.0-www-classic-6ac51f93"; - - /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ -if ( - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop === - 'function' -) { - __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error()); -} - +exports.version = "18.3.0-www-classic-85f17816"; +"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && + "function" === + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && + __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error()); diff --git a/compiled/facebook-www/React-profiling.modern.js b/compiled/facebook-www/React-profiling.modern.js index efeaaf233beb5..4a4c1e10c1820 100644 --- a/compiled/facebook-www/React-profiling.modern.js +++ b/compiled/facebook-www/React-profiling.modern.js @@ -1,27 +1,20 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @noflow - * @nolint - * @preventMunge - * @preserve-invariant-messages - */ +/* + Copyright (c) Meta Platforms, Inc. and affiliates. - 'use strict'; + This source code is licensed under the MIT license found in the + LICENSE file in the root directory of this source tree. -/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ -if ( - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart === - 'function' -) { - __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); -} - "use strict"; + @noflow + @nolint + @preventMunge + @preserve-invariant-messages +*/ +"use strict"; +"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && + "function" === + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && + __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error()); var REACT_ELEMENT_TYPE = Symbol.for("react.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), @@ -590,14 +583,8 @@ exports.useSyncExternalStore = function ( exports.useTransition = function () { return ReactCurrentDispatcher.current.useTransition(); }; -exports.version = "18.3.0-www-modern-93466d22"; - - /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ -if ( - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop === - 'function' -) { - __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error()); -} - +exports.version = "18.3.0-www-modern-4e52ff56"; +"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && + "function" === + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && + __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error()); diff --git a/compiled/facebook-www/ReactART-dev.classic.js b/compiled/facebook-www/ReactART-dev.classic.js index e8d56d653879c..50edf27c3680d 100644 --- a/compiled/facebook-www/ReactART-dev.classic.js +++ b/compiled/facebook-www/ReactART-dev.classic.js @@ -1,4 +1,5 @@ /** + * @preserve * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the @@ -10,29162 +11,29683 @@ * @preserve-invariant-messages */ -'use strict'; +"use strict"; if (__DEV__) { - (function() { + (function () { + "use strict"; - 'use strict'; + /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ + if ( + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined" && + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart === + "function" + ) { + __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); + } + var React = require("react"); + var Transform = require("art/core/transform"); + var Mode$1 = require("art/modes/current"); + var Scheduler = require("scheduler"); + var FastNoSideEffects = require("art/modes/fast-noSideEffects"); + + function _extends() { + _extends = + Object.assign || + function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } -/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ -if ( - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart === - 'function' -) { - __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); -} - "use strict"; + return target; + }; -var React = require("react"); -var Transform = require("art/core/transform"); -var Mode$1 = require("art/modes/current"); -var Scheduler = require("scheduler"); -var FastNoSideEffects = require("art/modes/fast-noSideEffects"); + return _extends.apply(this, arguments); + } -function _extends() { - _extends = - Object.assign || - function (target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i]; + function _inheritsLoose(subClass, superClass) { + subClass.prototype = Object.create(superClass.prototype); + subClass.prototype.constructor = subClass; + subClass.__proto__ = superClass; + } - for (var key in source) { - if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError( + "this hasn't been initialised - super() hasn't been called" + ); } - return target; - }; + return self; + } - return _extends.apply(this, arguments); -} + var ReactVersion = "18.3.0-www-classic-2bc98809"; -function _inheritsLoose(subClass, superClass) { - subClass.prototype = Object.create(superClass.prototype); - subClass.prototype.constructor = subClass; - subClass.__proto__ = superClass; -} + var LegacyRoot = 0; + var ConcurrentRoot = 1; -function _assertThisInitialized(self) { - if (self === void 0) { - throw new ReferenceError( - "this hasn't been initialised - super() hasn't been called" - ); - } + // This refers to a WWW module. + var warningWWW = require("warning"); - return self; -} + var suppressWarning = false; + function setSuppressWarning(newSuppressWarning) { + { + suppressWarning = newSuppressWarning; + } + } + function warn(format) { + { + if (!suppressWarning) { + for ( + var _len = arguments.length, + args = new Array(_len > 1 ? _len - 1 : 0), + _key = 1; + _key < _len; + _key++ + ) { + args[_key - 1] = arguments[_key]; + } + + printWarning("warn", format, args); + } + } + } + function error(format) { + { + if (!suppressWarning) { + for ( + var _len2 = arguments.length, + args = new Array(_len2 > 1 ? _len2 - 1 : 0), + _key2 = 1; + _key2 < _len2; + _key2++ + ) { + args[_key2 - 1] = arguments[_key2]; + } -var ReactVersion = "18.3.0-www-classic-44d9eb8b"; + printWarning("error", format, args); + } + } + } -var LegacyRoot = 0; -var ConcurrentRoot = 1; + function printWarning(level, format, args) { + { + var React = require("react"); -// This refers to a WWW module. -var warningWWW = require("warning"); + var ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. -var suppressWarning = false; -function setSuppressWarning(newSuppressWarning) { - { - suppressWarning = newSuppressWarning; - } -} -function warn(format) { - { - if (!suppressWarning) { - for ( - var _len = arguments.length, - args = new Array(_len > 1 ? _len - 1 : 0), - _key = 1; - _key < _len; - _key++ - ) { - args[_key - 1] = arguments[_key]; - } + if (ReactSharedInternals != null) { + var ReactDebugCurrentFrame = + ReactSharedInternals.ReactDebugCurrentFrame; + var stack = ReactDebugCurrentFrame.getStackAddendum(); - printWarning("warn", format, args); - } - } -} -function error(format) { - { - if (!suppressWarning) { - for ( - var _len2 = arguments.length, - args = new Array(_len2 > 1 ? _len2 - 1 : 0), - _key2 = 1; - _key2 < _len2; - _key2++ - ) { - args[_key2 - 1] = arguments[_key2]; - } + if (stack !== "") { + format += "%s"; + args.push(stack); + } + } // TODO: don't ignore level and pass it down somewhere too. - printWarning("error", format, args); + args.unshift(format); + args.unshift(false); + warningWWW.apply(null, args); + } } - } -} -function printWarning(level, format, args) { - { - var React = require("react"); + var assign = Object.assign; + + /** + * `ReactInstanceMap` maintains a mapping from a public facing stateful + * instance (key) and the internal representation (value). This allows public + * methods to accept the user facing instance as an argument and map them back + * to internal methods. + * + * Note that this module is currently shared and assumed to be stateless. + * If this becomes an actual Map, that will break. + */ + function get(key) { + return key._reactInternals; + } + function set(key, value) { + key._reactInternals = value; + } var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; + + // Re-export dynamic flags from the www version. + var dynamicFeatureFlags = require("ReactFeatureFlags"); + + var replayFailedUnitOfWorkWithInvokeGuardedCallback = + dynamicFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback, + enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, + enableUseRefAccessWarning = dynamicFeatureFlags.enableUseRefAccessWarning, + enableLazyContextPropagation = + dynamicFeatureFlags.enableLazyContextPropagation, + enableUnifiedSyncLane = dynamicFeatureFlags.enableUnifiedSyncLane, + enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, + enableDeferRootSchedulingToMicrotask = + dynamicFeatureFlags.enableDeferRootSchedulingToMicrotask, + enableAsyncActions = dynamicFeatureFlags.enableAsyncActions, + alwaysThrottleRetries = dynamicFeatureFlags.alwaysThrottleRetries, + enableDO_NOT_USE_disableStrictPassiveEffect = + dynamicFeatureFlags.enableDO_NOT_USE_disableStrictPassiveEffect, + disableSchedulerTimeoutInWorkLoop = + dynamicFeatureFlags.disableSchedulerTimeoutInWorkLoop, + enableUseDeferredValueInitialArg = + dynamicFeatureFlags.enableUseDeferredValueInitialArg; // On WWW, false is used for a new modern build. + var enableProfilerTimer = true; + var enableProfilerCommitHooks = true; + var enableProfilerNestedUpdatePhase = true; + var enableProfilerNestedUpdateScheduledHook = + dynamicFeatureFlags.enableProfilerNestedUpdateScheduledHook; + var createRootStrictEffectsByDefault = false; + + var enableSchedulingProfiler = dynamicFeatureFlags.enableSchedulingProfiler; // Note: we'll want to remove this when we to userland implementation. + + var FunctionComponent = 0; + var ClassComponent = 1; + var IndeterminateComponent = 2; // Before we know whether it is function or class + + var HostRoot = 3; // Root of a host tree. Could be nested inside another node. + + var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. + + var HostComponent = 5; + var HostText = 6; + var Fragment = 7; + var Mode = 8; + var ContextConsumer = 9; + var ContextProvider = 10; + var ForwardRef = 11; + var Profiler = 12; + var SuspenseComponent = 13; + var MemoComponent = 14; + var SimpleMemoComponent = 15; + var LazyComponent = 16; + var IncompleteClassComponent = 17; + var DehydratedFragment = 18; + var SuspenseListComponent = 19; + var ScopeComponent = 21; + var OffscreenComponent = 22; + var LegacyHiddenComponent = 23; + var CacheComponent = 24; + var TracingMarkerComponent = 25; + var HostHoistable = 26; + var HostSingleton = 27; + + // ATTENTION + // When adding new symbols to this file, + // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' + // The Symbol used to tag the ReactElement-like types. + var REACT_ELEMENT_TYPE = Symbol.for("react.element"); + var REACT_PORTAL_TYPE = Symbol.for("react.portal"); + var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); + var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); + var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); + var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); + var REACT_CONTEXT_TYPE = Symbol.for("react.context"); + var REACT_SERVER_CONTEXT_TYPE = Symbol.for("react.server_context"); + var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); + var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); + var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); + var REACT_MEMO_TYPE = Symbol.for("react.memo"); + var REACT_LAZY_TYPE = Symbol.for("react.lazy"); + var REACT_SCOPE_TYPE = Symbol.for("react.scope"); + var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); + var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); + var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); + var REACT_CACHE_TYPE = Symbol.for("react.cache"); + var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); + var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel"); + var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; + var FAUX_ITERATOR_SYMBOL = "@@iterator"; + function getIteratorFn(maybeIterable) { + if (maybeIterable === null || typeof maybeIterable !== "object") { + return null; + } - if (ReactSharedInternals != null) { - var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - var stack = ReactDebugCurrentFrame.getStackAddendum(); + var maybeIterator = + (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || + maybeIterable[FAUX_ITERATOR_SYMBOL]; - if (stack !== "") { - format += "%s"; - args.push(stack); + if (typeof maybeIterator === "function") { + return maybeIterator; } - } // TODO: don't ignore level and pass it down somewhere too. - args.unshift(format); - args.unshift(false); - warningWWW.apply(null, args); - } -} + return null; + } -var assign = Object.assign; + function getWrappedName$1(outerType, innerType, wrapperName) { + var displayName = outerType.displayName; -/** - * `ReactInstanceMap` maintains a mapping from a public facing stateful - * instance (key) and the internal representation (value). This allows public - * methods to accept the user facing instance as an argument and map them back - * to internal methods. - * - * Note that this module is currently shared and assumed to be stateless. - * If this becomes an actual Map, that will break. - */ -function get(key) { - return key._reactInternals; -} -function set(key, value) { - key._reactInternals = value; -} + if (displayName) { + return displayName; + } -var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; - -// Re-export dynamic flags from the www version. -var dynamicFeatureFlags = require("ReactFeatureFlags"); - -var replayFailedUnitOfWorkWithInvokeGuardedCallback = - dynamicFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback, - enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, - enableUseRefAccessWarning = dynamicFeatureFlags.enableUseRefAccessWarning, - enableLazyContextPropagation = - dynamicFeatureFlags.enableLazyContextPropagation, - enableUnifiedSyncLane = dynamicFeatureFlags.enableUnifiedSyncLane, - enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, - enableDeferRootSchedulingToMicrotask = - dynamicFeatureFlags.enableDeferRootSchedulingToMicrotask, - enableAsyncActions = dynamicFeatureFlags.enableAsyncActions, - alwaysThrottleRetries = dynamicFeatureFlags.alwaysThrottleRetries, - enableDO_NOT_USE_disableStrictPassiveEffect = - dynamicFeatureFlags.enableDO_NOT_USE_disableStrictPassiveEffect, - disableSchedulerTimeoutInWorkLoop = - dynamicFeatureFlags.disableSchedulerTimeoutInWorkLoop, - enableUseDeferredValueInitialArg = - dynamicFeatureFlags.enableUseDeferredValueInitialArg; // On WWW, false is used for a new modern build. -var enableProfilerTimer = true; -var enableProfilerCommitHooks = true; -var enableProfilerNestedUpdatePhase = true; -var enableProfilerNestedUpdateScheduledHook = - dynamicFeatureFlags.enableProfilerNestedUpdateScheduledHook; -var createRootStrictEffectsByDefault = false; - -var enableSchedulingProfiler = dynamicFeatureFlags.enableSchedulingProfiler; // Note: we'll want to remove this when we to userland implementation. - -var FunctionComponent = 0; -var ClassComponent = 1; -var IndeterminateComponent = 2; // Before we know whether it is function or class - -var HostRoot = 3; // Root of a host tree. Could be nested inside another node. - -var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. - -var HostComponent = 5; -var HostText = 6; -var Fragment = 7; -var Mode = 8; -var ContextConsumer = 9; -var ContextProvider = 10; -var ForwardRef = 11; -var Profiler = 12; -var SuspenseComponent = 13; -var MemoComponent = 14; -var SimpleMemoComponent = 15; -var LazyComponent = 16; -var IncompleteClassComponent = 17; -var DehydratedFragment = 18; -var SuspenseListComponent = 19; -var ScopeComponent = 21; -var OffscreenComponent = 22; -var LegacyHiddenComponent = 23; -var CacheComponent = 24; -var TracingMarkerComponent = 25; -var HostHoistable = 26; -var HostSingleton = 27; - -// ATTENTION -// When adding new symbols to this file, -// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' -// The Symbol used to tag the ReactElement-like types. -var REACT_ELEMENT_TYPE = Symbol.for("react.element"); -var REACT_PORTAL_TYPE = Symbol.for("react.portal"); -var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); -var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); -var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); -var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); -var REACT_CONTEXT_TYPE = Symbol.for("react.context"); -var REACT_SERVER_CONTEXT_TYPE = Symbol.for("react.server_context"); -var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); -var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); -var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); -var REACT_MEMO_TYPE = Symbol.for("react.memo"); -var REACT_LAZY_TYPE = Symbol.for("react.lazy"); -var REACT_SCOPE_TYPE = Symbol.for("react.scope"); -var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); -var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); -var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); -var REACT_CACHE_TYPE = Symbol.for("react.cache"); -var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); -var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel"); -var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; -var FAUX_ITERATOR_SYMBOL = "@@iterator"; -function getIteratorFn(maybeIterable) { - if (maybeIterable === null || typeof maybeIterable !== "object") { - return null; - } - - var maybeIterator = - (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || - maybeIterable[FAUX_ITERATOR_SYMBOL]; - - if (typeof maybeIterator === "function") { - return maybeIterator; - } - - return null; -} + var functionName = innerType.displayName || innerType.name || ""; + return functionName !== "" + ? wrapperName + "(" + functionName + ")" + : wrapperName; + } // Keep in sync with react-reconciler/getComponentNameFromFiber -function getWrappedName$1(outerType, innerType, wrapperName) { - var displayName = outerType.displayName; - - if (displayName) { - return displayName; - } - - var functionName = innerType.displayName || innerType.name || ""; - return functionName !== "" - ? wrapperName + "(" + functionName + ")" - : wrapperName; -} // Keep in sync with react-reconciler/getComponentNameFromFiber - -function getContextName$1(type) { - return type.displayName || "Context"; -} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. - -function getComponentNameFromType(type) { - if (type == null) { - // Host root, text node or just invalid type. - return null; - } - - { - if (typeof type.tag === "number") { - error( - "Received an unexpected object in getComponentNameFromType(). " + - "This is likely a bug in React. Please file an issue." - ); - } - } + function getContextName$1(type) { + return type.displayName || "Context"; + } // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. + + function getComponentNameFromType(type) { + if (type == null) { + // Host root, text node or just invalid type. + return null; + } + + { + if (typeof type.tag === "number") { + error( + "Received an unexpected object in getComponentNameFromType(). " + + "This is likely a bug in React. Please file an issue." + ); + } + } - if (typeof type === "function") { - return type.displayName || type.name || null; - } + if (typeof type === "function") { + return type.displayName || type.name || null; + } - if (typeof type === "string") { - return type; - } + if (typeof type === "string") { + return type; + } - switch (type) { - case REACT_FRAGMENT_TYPE: - return "Fragment"; + switch (type) { + case REACT_FRAGMENT_TYPE: + return "Fragment"; - case REACT_PORTAL_TYPE: - return "Portal"; + case REACT_PORTAL_TYPE: + return "Portal"; - case REACT_PROFILER_TYPE: - return "Profiler"; + case REACT_PROFILER_TYPE: + return "Profiler"; - case REACT_STRICT_MODE_TYPE: - return "StrictMode"; + case REACT_STRICT_MODE_TYPE: + return "StrictMode"; - case REACT_SUSPENSE_TYPE: - return "Suspense"; + case REACT_SUSPENSE_TYPE: + return "Suspense"; - case REACT_SUSPENSE_LIST_TYPE: - return "SuspenseList"; + case REACT_SUSPENSE_LIST_TYPE: + return "SuspenseList"; - case REACT_CACHE_TYPE: { - return "Cache"; - } + case REACT_CACHE_TYPE: { + return "Cache"; + } - // Fall through + // Fall through - case REACT_TRACING_MARKER_TYPE: - if (enableTransitionTracing) { - return "TracingMarker"; + case REACT_TRACING_MARKER_TYPE: + if (enableTransitionTracing) { + return "TracingMarker"; + } } - } - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_CONTEXT_TYPE: - var context = type; - return getContextName$1(context) + ".Consumer"; + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_CONTEXT_TYPE: + var context = type; + return getContextName$1(context) + ".Consumer"; - case REACT_PROVIDER_TYPE: - var provider = type; - return getContextName$1(provider._context) + ".Provider"; + case REACT_PROVIDER_TYPE: + var provider = type; + return getContextName$1(provider._context) + ".Provider"; - case REACT_FORWARD_REF_TYPE: - return getWrappedName$1(type, type.render, "ForwardRef"); + case REACT_FORWARD_REF_TYPE: + return getWrappedName$1(type, type.render, "ForwardRef"); - case REACT_MEMO_TYPE: - var outerName = type.displayName || null; + case REACT_MEMO_TYPE: + var outerName = type.displayName || null; - if (outerName !== null) { - return outerName; - } + if (outerName !== null) { + return outerName; + } - return getComponentNameFromType(type.type) || "Memo"; + return getComponentNameFromType(type.type) || "Memo"; - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - try { - return getComponentNameFromType(init(payload)); - } catch (x) { - return null; + try { + return getComponentNameFromType(init(payload)); + } catch (x) { + return null; + } + } } } - } - } - - return null; -} - -function getWrappedName(outerType, innerType, wrapperName) { - var functionName = innerType.displayName || innerType.name || ""; - return ( - outerType.displayName || - (functionName !== "" ? wrapperName + "(" + functionName + ")" : wrapperName) - ); -} // Keep in sync with shared/getComponentNameFromType - -function getContextName(type) { - return type.displayName || "Context"; -} - -function getComponentNameFromFiber(fiber) { - var tag = fiber.tag, - type = fiber.type; - switch (tag) { - case CacheComponent: - return "Cache"; + return null; + } - case ContextConsumer: - var context = type; - return getContextName(context) + ".Consumer"; + function getWrappedName(outerType, innerType, wrapperName) { + var functionName = innerType.displayName || innerType.name || ""; + return ( + outerType.displayName || + (functionName !== "" + ? wrapperName + "(" + functionName + ")" + : wrapperName) + ); + } // Keep in sync with shared/getComponentNameFromType - case ContextProvider: - var provider = type; - return getContextName(provider._context) + ".Provider"; + function getContextName(type) { + return type.displayName || "Context"; + } - case DehydratedFragment: - return "DehydratedFragment"; + function getComponentNameFromFiber(fiber) { + var tag = fiber.tag, + type = fiber.type; - case ForwardRef: - return getWrappedName(type, type.render, "ForwardRef"); + switch (tag) { + case CacheComponent: + return "Cache"; - case Fragment: - return "Fragment"; + case ContextConsumer: + var context = type; + return getContextName(context) + ".Consumer"; - case HostHoistable: - case HostSingleton: - case HostComponent: - // Host component type is the display name (e.g. "div", "View") - return type; + case ContextProvider: + var provider = type; + return getContextName(provider._context) + ".Provider"; - case HostPortal: - return "Portal"; + case DehydratedFragment: + return "DehydratedFragment"; - case HostRoot: - return "Root"; + case ForwardRef: + return getWrappedName(type, type.render, "ForwardRef"); - case HostText: - return "Text"; + case Fragment: + return "Fragment"; - case LazyComponent: - // Name comes from the type in this case; we don't have a tag. - return getComponentNameFromType(type); + case HostHoistable: + case HostSingleton: + case HostComponent: + // Host component type is the display name (e.g. "div", "View") + return type; - case Mode: - if (type === REACT_STRICT_MODE_TYPE) { - // Don't be less specific than shared/getComponentNameFromType - return "StrictMode"; - } + case HostPortal: + return "Portal"; - return "Mode"; + case HostRoot: + return "Root"; - case OffscreenComponent: - return "Offscreen"; + case HostText: + return "Text"; - case Profiler: - return "Profiler"; + case LazyComponent: + // Name comes from the type in this case; we don't have a tag. + return getComponentNameFromType(type); - case ScopeComponent: - return "Scope"; + case Mode: + if (type === REACT_STRICT_MODE_TYPE) { + // Don't be less specific than shared/getComponentNameFromType + return "StrictMode"; + } - case SuspenseComponent: - return "Suspense"; + return "Mode"; - case SuspenseListComponent: - return "SuspenseList"; + case OffscreenComponent: + return "Offscreen"; - case TracingMarkerComponent: - return "TracingMarker"; - // The display name for this tags come from the user-provided type: + case Profiler: + return "Profiler"; - case ClassComponent: - case FunctionComponent: - case IncompleteClassComponent: - case IndeterminateComponent: - case MemoComponent: - case SimpleMemoComponent: - if (typeof type === "function") { - return type.displayName || type.name || null; - } + case ScopeComponent: + return "Scope"; - if (typeof type === "string") { - return type; - } + case SuspenseComponent: + return "Suspense"; - break; + case SuspenseListComponent: + return "SuspenseList"; - case LegacyHiddenComponent: { - return "LegacyHidden"; - } - } + case TracingMarkerComponent: + return "TracingMarker"; + // The display name for this tags come from the user-provided type: - return null; -} + case ClassComponent: + case FunctionComponent: + case IncompleteClassComponent: + case IndeterminateComponent: + case MemoComponent: + case SimpleMemoComponent: + if (typeof type === "function") { + return type.displayName || type.name || null; + } -var NoFlags$1 = - /* */ - 0; -var PerformedWork = - /* */ - 1; -var Placement = - /* */ - 2; -var DidCapture = - /* */ - 128; -var Hydrating = - /* */ - 4096; // You can change the rest (and add more). - -var Update = - /* */ - 4; -/* Skipped value: 0b0000000000000000000000001000; */ - -var ChildDeletion = - /* */ - 16; -var ContentReset = - /* */ - 32; -var Callback = - /* */ - 64; -/* Used by DidCapture: 0b0000000000000000000010000000; */ - -var ForceClientRender = - /* */ - 256; -var Ref = - /* */ - 512; -var Snapshot = - /* */ - 1024; -var Passive$1 = - /* */ - 2048; -/* Used by Hydrating: 0b0000000000000001000000000000; */ - -var Visibility = - /* */ - 8192; -var StoreConsistency = - /* */ - 16384; // It's OK to reuse these bits because these flags are mutually exclusive for -// different fiber types. We should really be doing this for as many flags as -// possible, because we're about to run out of bits. - -var ScheduleRetry = StoreConsistency; -var ShouldSuspendCommit = Visibility; -var LifecycleEffectMask = - Passive$1 | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit) - -var HostEffectMask = - /* */ - 32767; // These are not really side effects, but we still reuse this field. - -var Incomplete = - /* */ - 32768; -var ShouldCapture = - /* */ - 65536; -var ForceUpdateForLegacySuspense = - /* */ - 131072; -var DidPropagateContext = - /* */ - 262144; -var NeedsPropagation = - /* */ - 524288; -var Forked = - /* */ - 1048576; // Static tags describe aspects of a fiber that are not specific to a render, -// e.g. a fiber uses a passive effect (even if there are no updates on this particular render). -// This enables us to defer more work in the unmount case, -// since we can defer traversing the tree during layout to look for Passive effects, -// and instead rely on the static flag as a signal that there may be cleanup work. - -var RefStatic = - /* */ - 2097152; -var LayoutStatic = - /* */ - 4194304; -var PassiveStatic = - /* */ - 8388608; -var MaySuspendCommit = - /* */ - 16777216; // Flag used to identify newly inserted fibers. It isn't reset after commit unlike `Placement`. - -var PlacementDEV = - /* */ - 33554432; -var MountLayoutDev = - /* */ - 67108864; -var MountPassiveDev = - /* */ - 134217728; // Groups of flags that are used in the commit phase to skip over trees that -// don't contain effects, by checking subtreeFlags. - -var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility - // flag logic (see #20043) - Update | - Snapshot | // createEventHandle needs to visit deleted and hidden trees to - // fire beforeblur - // TODO: Only need to visit Deletions during BeforeMutation phase if an - // element is focused. - (ChildDeletion | Visibility); -var MutationMask = - Placement | - Update | - ChildDeletion | - ContentReset | - Ref | - Hydrating | - Visibility; -var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask - -var PassiveMask = Passive$1 | Visibility | ChildDeletion; // Union of tags that don't get reset on clones. -// This allows certain concepts to persist without recalculating them, -// e.g. whether a subtree contains passive effects or portals. - -var StaticMask = LayoutStatic | PassiveStatic | RefStatic | MaySuspendCommit; - -var ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner; -function getNearestMountedFiber(fiber) { - var node = fiber; - var nearestMounted = fiber; - - if (!fiber.alternate) { - // If there is no alternate, this might be a new tree that isn't inserted - // yet. If it is, then it will have a pending insertion effect on it. - var nextNode = node; - - do { - node = nextNode; - - if ((node.flags & (Placement | Hydrating)) !== NoFlags$1) { - // This is an insertion or in-progress hydration. The nearest possible - // mounted fiber is the parent but we need to continue to figure out - // if that one is still mounted. - nearestMounted = node.return; - } // $FlowFixMe[incompatible-type] we bail out when we get a null - - nextNode = node.return; - } while (nextNode); - } else { - while (node.return) { - node = node.return; - } - } - - if (node.tag === HostRoot) { - // TODO: Check if this was a nested HostRoot when used with - // renderContainerIntoSubtree. - return nearestMounted; - } // If we didn't hit the root, that means that we're in an disconnected tree - // that has been unmounted. - - return null; -} -function isFiberMounted(fiber) { - return getNearestMountedFiber(fiber) === fiber; -} -function isMounted(component) { - { - var owner = ReactCurrentOwner$2.current; + if (typeof type === "string") { + return type; + } - if (owner !== null && owner.tag === ClassComponent) { - var ownerFiber = owner; - var instance = ownerFiber.stateNode; + break; - if (!instance._warnedAboutRefsInRender) { - 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" - ); + case LegacyHiddenComponent: { + return "LegacyHidden"; + } } - instance._warnedAboutRefsInRender = true; + return null; } - } - - var fiber = get(component); - if (!fiber) { - return false; - } - - return getNearestMountedFiber(fiber) === fiber; -} + var NoFlags$1 = + /* */ + 0; + var PerformedWork = + /* */ + 1; + var Placement = + /* */ + 2; + var DidCapture = + /* */ + 128; + var Hydrating = + /* */ + 4096; // You can change the rest (and add more). + + var Update = + /* */ + 4; + /* Skipped value: 0b0000000000000000000000001000; */ + + var ChildDeletion = + /* */ + 16; + var ContentReset = + /* */ + 32; + var Callback = + /* */ + 64; + /* Used by DidCapture: 0b0000000000000000000010000000; */ + + var ForceClientRender = + /* */ + 256; + var Ref = + /* */ + 512; + var Snapshot = + /* */ + 1024; + var Passive$1 = + /* */ + 2048; + /* Used by Hydrating: 0b0000000000000001000000000000; */ + + var Visibility = + /* */ + 8192; + var StoreConsistency = + /* */ + 16384; // It's OK to reuse these bits because these flags are mutually exclusive for + // different fiber types. We should really be doing this for as many flags as + // possible, because we're about to run out of bits. + + var ScheduleRetry = StoreConsistency; + var ShouldSuspendCommit = Visibility; + var LifecycleEffectMask = + Passive$1 | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit) + + var HostEffectMask = + /* */ + 32767; // These are not really side effects, but we still reuse this field. + + var Incomplete = + /* */ + 32768; + var ShouldCapture = + /* */ + 65536; + var ForceUpdateForLegacySuspense = + /* */ + 131072; + var DidPropagateContext = + /* */ + 262144; + var NeedsPropagation = + /* */ + 524288; + var Forked = + /* */ + 1048576; // Static tags describe aspects of a fiber that are not specific to a render, + // e.g. a fiber uses a passive effect (even if there are no updates on this particular render). + // This enables us to defer more work in the unmount case, + // since we can defer traversing the tree during layout to look for Passive effects, + // and instead rely on the static flag as a signal that there may be cleanup work. + + var RefStatic = + /* */ + 2097152; + var LayoutStatic = + /* */ + 4194304; + var PassiveStatic = + /* */ + 8388608; + var MaySuspendCommit = + /* */ + 16777216; // Flag used to identify newly inserted fibers. It isn't reset after commit unlike `Placement`. + + var PlacementDEV = + /* */ + 33554432; + var MountLayoutDev = + /* */ + 67108864; + var MountPassiveDev = + /* */ + 134217728; // Groups of flags that are used in the commit phase to skip over trees that + // don't contain effects, by checking subtreeFlags. + + var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility + // flag logic (see #20043) + Update | + Snapshot | // createEventHandle needs to visit deleted and hidden trees to + // fire beforeblur + // TODO: Only need to visit Deletions during BeforeMutation phase if an + // element is focused. + (ChildDeletion | Visibility); + var MutationMask = + Placement | + Update | + ChildDeletion | + ContentReset | + Ref | + Hydrating | + Visibility; + var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask + + var PassiveMask = Passive$1 | Visibility | ChildDeletion; // Union of tags that don't get reset on clones. + // This allows certain concepts to persist without recalculating them, + // e.g. whether a subtree contains passive effects or portals. + + var StaticMask = + LayoutStatic | PassiveStatic | RefStatic | MaySuspendCommit; + + var ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner; + function getNearestMountedFiber(fiber) { + var node = fiber; + var nearestMounted = fiber; + + if (!fiber.alternate) { + // If there is no alternate, this might be a new tree that isn't inserted + // yet. If it is, then it will have a pending insertion effect on it. + var nextNode = node; -function assertIsMounted(fiber) { - if (getNearestMountedFiber(fiber) !== fiber) { - throw new Error("Unable to find node on an unmounted component."); - } -} + do { + node = nextNode; -function findCurrentFiberUsingSlowPath(fiber) { - var alternate = fiber.alternate; + if ((node.flags & (Placement | Hydrating)) !== NoFlags$1) { + // This is an insertion or in-progress hydration. The nearest possible + // mounted fiber is the parent but we need to continue to figure out + // if that one is still mounted. + nearestMounted = node.return; + } // $FlowFixMe[incompatible-type] we bail out when we get a null - if (!alternate) { - // If there is no alternate, then we only need to check if it is mounted. - var nearestMounted = getNearestMountedFiber(fiber); + nextNode = node.return; + } while (nextNode); + } else { + while (node.return) { + node = node.return; + } + } - if (nearestMounted === null) { - throw new Error("Unable to find node on an unmounted component."); - } + if (node.tag === HostRoot) { + // TODO: Check if this was a nested HostRoot when used with + // renderContainerIntoSubtree. + return nearestMounted; + } // If we didn't hit the root, that means that we're in an disconnected tree + // that has been unmounted. - if (nearestMounted !== fiber) { return null; } + function isFiberMounted(fiber) { + return getNearestMountedFiber(fiber) === fiber; + } + function isMounted(component) { + { + var owner = ReactCurrentOwner$2.current; - return fiber; - } // If we have two possible branches, we'll walk backwards up to the root - // to see what path the root points to. On the way we may hit one of the - // special cases and we'll deal with them. + if (owner !== null && owner.tag === ClassComponent) { + var ownerFiber = owner; + var instance = ownerFiber.stateNode; - var a = fiber; - var b = alternate; + if (!instance._warnedAboutRefsInRender) { + 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" + ); + } - while (true) { - var parentA = a.return; + instance._warnedAboutRefsInRender = true; + } + } - if (parentA === null) { - // We're at the root. - break; - } + var fiber = get(component); - var parentB = parentA.alternate; + if (!fiber) { + return false; + } - if (parentB === null) { - // There is no alternate. This is an unusual case. Currently, it only - // happens when a Suspense component is hidden. An extra fragment fiber - // is inserted in between the Suspense fiber and its children. Skip - // over this extra fragment fiber and proceed to the next parent. - var nextParent = parentA.return; + return getNearestMountedFiber(fiber) === fiber; + } - if (nextParent !== null) { - a = b = nextParent; - continue; - } // If there's no parent, we're at the root. + function assertIsMounted(fiber) { + if (getNearestMountedFiber(fiber) !== fiber) { + throw new Error("Unable to find node on an unmounted component."); + } + } - break; - } // If both copies of the parent fiber point to the same child, we can - // assume that the child is current. This happens when we bailout on low - // priority: the bailed out fiber's child reuses the current child. + function findCurrentFiberUsingSlowPath(fiber) { + var alternate = fiber.alternate; - if (parentA.child === parentB.child) { - var child = parentA.child; + if (!alternate) { + // If there is no alternate, then we only need to check if it is mounted. + var nearestMounted = getNearestMountedFiber(fiber); - while (child) { - if (child === a) { - // We've determined that A is the current branch. - assertIsMounted(parentA); - return fiber; + if (nearestMounted === null) { + throw new Error("Unable to find node on an unmounted component."); } - if (child === b) { - // We've determined that B is the current branch. - assertIsMounted(parentA); - return alternate; + if (nearestMounted !== fiber) { + return null; } - child = child.sibling; - } // We should never have an alternate for any mounting node. So the only - // way this could possibly happen is if this was unmounted, if at all. + return fiber; + } // If we have two possible branches, we'll walk backwards up to the root + // to see what path the root points to. On the way we may hit one of the + // special cases and we'll deal with them. - throw new Error("Unable to find node on an unmounted component."); - } + var a = fiber; + var b = alternate; - if (a.return !== b.return) { - // The return pointer of A and the return pointer of B point to different - // fibers. We assume that return pointers never criss-cross, so A must - // belong to the child set of A.return, and B must belong to the child - // set of B.return. - a = parentA; - b = parentB; - } else { - // The return pointers point to the same fiber. We'll have to use the - // default, slow path: scan the child sets of each parent alternate to see - // which child belongs to which set. - // - // Search parent A's child set - var didFindChild = false; - var _child = parentA.child; + while (true) { + var parentA = a.return; - while (_child) { - if (_child === a) { - didFindChild = true; - a = parentA; - b = parentB; + if (parentA === null) { + // We're at the root. break; } - if (_child === b) { - didFindChild = true; - b = parentA; - a = parentB; - break; - } + var parentB = parentA.alternate; - _child = _child.sibling; - } + if (parentB === null) { + // There is no alternate. This is an unusual case. Currently, it only + // happens when a Suspense component is hidden. An extra fragment fiber + // is inserted in between the Suspense fiber and its children. Skip + // over this extra fragment fiber and proceed to the next parent. + var nextParent = parentA.return; - if (!didFindChild) { - // Search parent B's child set - _child = parentB.child; + if (nextParent !== null) { + a = b = nextParent; + continue; + } // If there's no parent, we're at the root. - while (_child) { - if (_child === a) { - didFindChild = true; - a = parentB; - b = parentA; - break; - } + break; + } // If both copies of the parent fiber point to the same child, we can + // assume that the child is current. This happens when we bailout on low + // priority: the bailed out fiber's child reuses the current child. + + if (parentA.child === parentB.child) { + var child = parentA.child; + + while (child) { + if (child === a) { + // We've determined that A is the current branch. + assertIsMounted(parentA); + return fiber; + } - if (_child === b) { - didFindChild = true; - b = parentB; - a = parentA; - break; - } + if (child === b) { + // We've determined that B is the current branch. + assertIsMounted(parentA); + return alternate; + } - _child = _child.sibling; - } + child = child.sibling; + } // We should never have an alternate for any mounting node. So the only + // way this could possibly happen is if this was unmounted, if at all. - if (!didFindChild) { - 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." - ); + throw new Error("Unable to find node on an unmounted component."); } - } - } - if (a.alternate !== b) { - 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." - ); - } - } // If the root is not a host container, we're in a disconnected tree. I.e. - // unmounted. - - if (a.tag !== HostRoot) { - throw new Error("Unable to find node on an unmounted component."); - } + if (a.return !== b.return) { + // The return pointer of A and the return pointer of B point to different + // fibers. We assume that return pointers never criss-cross, so A must + // belong to the child set of A.return, and B must belong to the child + // set of B.return. + a = parentA; + b = parentB; + } else { + // The return pointers point to the same fiber. We'll have to use the + // default, slow path: scan the child sets of each parent alternate to see + // which child belongs to which set. + // + // Search parent A's child set + var didFindChild = false; + var _child = parentA.child; + + while (_child) { + if (_child === a) { + didFindChild = true; + a = parentA; + b = parentB; + break; + } - if (a.stateNode.current === a) { - // We've determined that A is the current branch. - return fiber; - } // Otherwise B has to be current branch. + if (_child === b) { + didFindChild = true; + b = parentA; + a = parentB; + break; + } - return alternate; -} -function findCurrentHostFiber(parent) { - var currentParent = findCurrentFiberUsingSlowPath(parent); - return currentParent !== null - ? findCurrentHostFiberImpl(currentParent) - : null; -} + _child = _child.sibling; + } -function findCurrentHostFiberImpl(node) { - // Next we'll drill down this component to find the first HostComponent/Text. - var tag = node.tag; + if (!didFindChild) { + // Search parent B's child set + _child = parentB.child; - if ( - tag === HostComponent || - tag === HostHoistable || - tag === HostSingleton || - tag === HostText - ) { - return node; - } + while (_child) { + if (_child === a) { + didFindChild = true; + a = parentB; + b = parentA; + break; + } - var child = node.child; + if (_child === b) { + didFindChild = true; + b = parentB; + a = parentA; + break; + } - while (child !== null) { - var match = findCurrentHostFiberImpl(child); + _child = _child.sibling; + } - if (match !== null) { - return match; - } + if (!didFindChild) { + 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." + ); + } + } + } - child = child.sibling; - } + if (a.alternate !== b) { + 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." + ); + } + } // If the root is not a host container, we're in a disconnected tree. I.e. + // unmounted. - return null; -} + if (a.tag !== HostRoot) { + throw new Error("Unable to find node on an unmounted component."); + } -function isFiberSuspenseAndTimedOut(fiber) { - var memoizedState = fiber.memoizedState; - return ( - fiber.tag === SuspenseComponent && - memoizedState !== null && - memoizedState.dehydrated === null - ); -} -function doesFiberContain(parentFiber, childFiber) { - var node = childFiber; - var parentFiberAlternate = parentFiber.alternate; + if (a.stateNode.current === a) { + // We've determined that A is the current branch. + return fiber; + } // Otherwise B has to be current branch. - while (node !== null) { - if (node === parentFiber || node === parentFiberAlternate) { - return true; + return alternate; + } + function findCurrentHostFiber(parent) { + var currentParent = findCurrentFiberUsingSlowPath(parent); + return currentParent !== null + ? findCurrentHostFiberImpl(currentParent) + : null; } - node = node.return; - } + function findCurrentHostFiberImpl(node) { + // Next we'll drill down this component to find the first HostComponent/Text. + var tag = node.tag; - return false; -} + if ( + tag === HostComponent || + tag === HostHoistable || + tag === HostSingleton || + tag === HostText + ) { + return node; + } -var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare + var child = node.child; -function isArray(a) { - return isArrayImpl(a); -} + while (child !== null) { + var match = findCurrentHostFiberImpl(child); -var TYPES = { - CLIPPING_RECTANGLE: "ClippingRectangle", - GROUP: "Group", - SHAPE: "Shape", - TEXT: "Text" -}; -var EVENT_TYPES = { - onClick: "click", - onMouseMove: "mousemove", - onMouseOver: "mouseover", - onMouseOut: "mouseout", - onMouseUp: "mouseup", - onMouseDown: "mousedown" -}; -function childrenAsString(children) { - if (!children) { - return ""; - } else if (typeof children === "string") { - return children; - } else if (children.length) { - return children.join(""); - } else { - return ""; - } -} + if (match !== null) { + return match; + } -// This module only exists as an ESM wrapper around the external CommonJS -var scheduleCallback$3 = Scheduler.unstable_scheduleCallback; -var cancelCallback$1 = Scheduler.unstable_cancelCallback; -var shouldYield = Scheduler.unstable_shouldYield; -var requestPaint = Scheduler.unstable_requestPaint; -var now$1 = Scheduler.unstable_now; -var ImmediatePriority = Scheduler.unstable_ImmediatePriority; -var UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; -var NormalPriority$1 = Scheduler.unstable_NormalPriority; -var IdlePriority = Scheduler.unstable_IdlePriority; // this doesn't actually exist on the scheduler, but it *does* -// on scheduler/unstable_mock, which we'll need for internal testing - -var log$2 = Scheduler.log; -var unstable_setDisableYieldValue = Scheduler.unstable_setDisableYieldValue; - -// Helpers to patch console.logs to avoid logging during side-effect free -// replaying on render function. This currently only patches the object -// lazily which won't cover if the log function was extracted eagerly. -// We could also eagerly patch the method. -var disabledDepth = 0; -var prevLog; -var prevInfo; -var prevWarn; -var prevError; -var prevGroup; -var prevGroupCollapsed; -var prevGroupEnd; - -function disabledLog() {} - -disabledLog.__reactDisabledLog = true; -function disableLogs() { - { - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - prevLog = console.log; - prevInfo = console.info; - prevWarn = console.warn; - prevError = console.error; - prevGroup = console.group; - prevGroupCollapsed = console.groupCollapsed; - prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 - - var props = { - configurable: true, - enumerable: true, - value: disabledLog, - writable: true - }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. - - Object.defineProperties(console, { - info: props, - log: props, - warn: props, - error: props, - group: props, - groupCollapsed: props, - groupEnd: props - }); - /* eslint-enable react-internal/no-production-logging */ - } + child = child.sibling; + } - disabledDepth++; - } -} -function reenableLogs() { - { - disabledDepth--; - - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - var props = { - configurable: true, - enumerable: true, - writable: true - }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. - - Object.defineProperties(console, { - log: assign({}, props, { - value: prevLog - }), - info: assign({}, props, { - value: prevInfo - }), - warn: assign({}, props, { - value: prevWarn - }), - error: assign({}, props, { - value: prevError - }), - group: assign({}, props, { - value: prevGroup - }), - groupCollapsed: assign({}, props, { - value: prevGroupCollapsed - }), - groupEnd: assign({}, props, { - value: prevGroupEnd - }) - }); - /* eslint-enable react-internal/no-production-logging */ + return null; } - if (disabledDepth < 0) { - error( - "disabledDepth fell below zero. " + - "This is a bug in React. Please file an issue." + function isFiberSuspenseAndTimedOut(fiber) { + var memoizedState = fiber.memoizedState; + return ( + fiber.tag === SuspenseComponent && + memoizedState !== null && + memoizedState.dehydrated === null ); } - } -} + function doesFiberContain(parentFiber, childFiber) { + var node = childFiber; + var parentFiberAlternate = parentFiber.alternate; -var rendererID = null; -var injectedHook = null; -var injectedProfilingHooks = null; -var hasLoggedError = false; -var isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined"; -function injectInternals(internals) { - if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { - // No DevTools - return false; - } - - var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - - if (hook.isDisabled) { - // This isn't a real property on the hook, but it can be set to opt out - // of DevTools integration and associated warnings and logs. - // https://github.com/facebook/react/issues/3877 - return true; - } - - if (!hook.supportsFiber) { - { - 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" - ); - } // DevTools exists, even though it doesn't support Fiber. - - return true; - } - - try { - if (enableSchedulingProfiler) { - // Conditionally inject these hooks only if Timeline profiler is supported by this build. - // This gives DevTools a way to feature detect that isn't tied to version number - // (since profiling and timeline are controlled by different feature flags). - internals = assign({}, internals, { - getLaneLabelMap: getLaneLabelMap, - injectProfilingHooks: injectProfilingHooks - }); - } + while (node !== null) { + if (node === parentFiber || node === parentFiberAlternate) { + return true; + } - rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. + node = node.return; + } - injectedHook = hook; - } catch (err) { - // Catch all errors because it is unsafe to throw during initialization. - { - error("React instrumentation encountered an error: %s.", err); + return false; } - } - if (hook.checkDCE) { - // This is the real DevTools. - return true; - } else { - // This is likely a hook installed by Fast Refresh runtime. - return false; - } -} -function onScheduleRoot(root, children) { - { - if ( - injectedHook && - typeof injectedHook.onScheduleFiberRoot === "function" - ) { - try { - injectedHook.onScheduleFiberRoot(rendererID, root, children); - } catch (err) { - if (!hasLoggedError) { - hasLoggedError = true; + var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare - error("React instrumentation encountered an error: %s", err); - } - } + function isArray(a) { + return isArrayImpl(a); } - } -} -function onCommitRoot(root, eventPriority) { - if (injectedHook && typeof injectedHook.onCommitFiberRoot === "function") { - try { - var didError = (root.current.flags & DidCapture) === DidCapture; - - if (enableProfilerTimer) { - var schedulerPriority; - - switch (eventPriority) { - case DiscreteEventPriority: - schedulerPriority = ImmediatePriority; - break; - case ContinuousEventPriority: - schedulerPriority = UserBlockingPriority; - break; - - case DefaultEventPriority: - schedulerPriority = NormalPriority$1; - break; - - case IdleEventPriority: - schedulerPriority = IdlePriority; - break; - - default: - schedulerPriority = NormalPriority$1; - break; + var TYPES = { + CLIPPING_RECTANGLE: "ClippingRectangle", + GROUP: "Group", + SHAPE: "Shape", + TEXT: "Text" + }; + var EVENT_TYPES = { + onClick: "click", + onMouseMove: "mousemove", + onMouseOver: "mouseover", + onMouseOut: "mouseout", + onMouseUp: "mouseup", + onMouseDown: "mousedown" + }; + function childrenAsString(children) { + if (!children) { + return ""; + } else if (typeof children === "string") { + return children; + } else if (children.length) { + return children.join(""); + } else { + return ""; + } + } + + // This module only exists as an ESM wrapper around the external CommonJS + var scheduleCallback$3 = Scheduler.unstable_scheduleCallback; + var cancelCallback$1 = Scheduler.unstable_cancelCallback; + var shouldYield = Scheduler.unstable_shouldYield; + var requestPaint = Scheduler.unstable_requestPaint; + var now$1 = Scheduler.unstable_now; + var ImmediatePriority = Scheduler.unstable_ImmediatePriority; + var UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; + var NormalPriority$1 = Scheduler.unstable_NormalPriority; + var IdlePriority = Scheduler.unstable_IdlePriority; // this doesn't actually exist on the scheduler, but it *does* + // on scheduler/unstable_mock, which we'll need for internal testing + + var log$2 = Scheduler.log; + var unstable_setDisableYieldValue = Scheduler.unstable_setDisableYieldValue; + + // Helpers to patch console.logs to avoid logging during side-effect free + // replaying on render function. This currently only patches the object + // lazily which won't cover if the log function was extracted eagerly. + // We could also eagerly patch the method. + var disabledDepth = 0; + var prevLog; + var prevInfo; + var prevWarn; + var prevError; + var prevGroup; + var prevGroupCollapsed; + var prevGroupEnd; + + function disabledLog() {} + + disabledLog.__reactDisabledLog = true; + function disableLogs() { + { + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + prevLog = console.log; + prevInfo = console.info; + prevWarn = console.warn; + prevError = console.error; + prevGroup = console.group; + prevGroupCollapsed = console.groupCollapsed; + prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 + + var props = { + configurable: true, + enumerable: true, + value: disabledLog, + writable: true + }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. + + Object.defineProperties(console, { + info: props, + log: props, + warn: props, + error: props, + group: props, + groupCollapsed: props, + groupEnd: props + }); + /* eslint-enable react-internal/no-production-logging */ } - injectedHook.onCommitFiberRoot( - rendererID, - root, - schedulerPriority, - didError - ); + disabledDepth++; } - } catch (err) { + } + function reenableLogs() { { - if (!hasLoggedError) { - hasLoggedError = true; + disabledDepth--; + + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + var props = { + configurable: true, + enumerable: true, + writable: true + }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. + + Object.defineProperties(console, { + log: assign({}, props, { + value: prevLog + }), + info: assign({}, props, { + value: prevInfo + }), + warn: assign({}, props, { + value: prevWarn + }), + error: assign({}, props, { + value: prevError + }), + group: assign({}, props, { + value: prevGroup + }), + groupCollapsed: assign({}, props, { + value: prevGroupCollapsed + }), + groupEnd: assign({}, props, { + value: prevGroupEnd + }) + }); + /* eslint-enable react-internal/no-production-logging */ + } - error("React instrumentation encountered an error: %s", err); + if (disabledDepth < 0) { + error( + "disabledDepth fell below zero. " + + "This is a bug in React. Please file an issue." + ); } } } - } -} -function onPostCommitRoot(root) { - if ( - injectedHook && - typeof injectedHook.onPostCommitFiberRoot === "function" - ) { - try { - injectedHook.onPostCommitFiberRoot(rendererID, root); - } catch (err) { - { - if (!hasLoggedError) { - hasLoggedError = true; - error("React instrumentation encountered an error: %s", err); - } + var rendererID = null; + var injectedHook = null; + var injectedProfilingHooks = null; + var hasLoggedError = false; + var isDevToolsPresent = + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined"; + function injectInternals(internals) { + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { + // No DevTools + return false; } - } - } -} -function onCommitUnmount(fiber) { - if (injectedHook && typeof injectedHook.onCommitFiberUnmount === "function") { - try { - injectedHook.onCommitFiberUnmount(rendererID, fiber); - } catch (err) { - { - if (!hasLoggedError) { - hasLoggedError = true; - error("React instrumentation encountered an error: %s", err); - } + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; + + if (hook.isDisabled) { + // This isn't a real property on the hook, but it can be set to opt out + // of DevTools integration and associated warnings and logs. + // https://github.com/facebook/react/issues/3877 + return true; + } + + if (!hook.supportsFiber) { + { + 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" + ); + } // DevTools exists, even though it doesn't support Fiber. + + return true; } - } - } -} -function setIsStrictModeForDevtools(newIsStrictMode) { - { - if (typeof log$2 === "function") { - // We're in a test because Scheduler.log only exists - // in SchedulerMock. To reduce the noise in strict mode tests, - // suppress warnings and disable scheduler yielding during the double render - unstable_setDisableYieldValue(newIsStrictMode); - setSuppressWarning(newIsStrictMode); - } - if (injectedHook && typeof injectedHook.setStrictMode === "function") { try { - injectedHook.setStrictMode(rendererID, newIsStrictMode); + if (enableSchedulingProfiler) { + // Conditionally inject these hooks only if Timeline profiler is supported by this build. + // This gives DevTools a way to feature detect that isn't tied to version number + // (since profiling and timeline are controlled by different feature flags). + internals = assign({}, internals, { + getLaneLabelMap: getLaneLabelMap, + injectProfilingHooks: injectProfilingHooks + }); + } + + rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. + + injectedHook = hook; } catch (err) { + // Catch all errors because it is unsafe to throw during initialization. { - if (!hasLoggedError) { - hasLoggedError = true; + error("React instrumentation encountered an error: %s.", err); + } + } + + if (hook.checkDCE) { + // This is the real DevTools. + return true; + } else { + // This is likely a hook installed by Fast Refresh runtime. + return false; + } + } + function onScheduleRoot(root, children) { + { + if ( + injectedHook && + typeof injectedHook.onScheduleFiberRoot === "function" + ) { + try { + injectedHook.onScheduleFiberRoot(rendererID, root, children); + } catch (err) { + if (!hasLoggedError) { + hasLoggedError = true; - error("React instrumentation encountered an error: %s", err); + error("React instrumentation encountered an error: %s", err); + } } } } } - } -} // Profiler API hooks - -function injectProfilingHooks(profilingHooks) { - injectedProfilingHooks = profilingHooks; -} + function onCommitRoot(root, eventPriority) { + if ( + injectedHook && + typeof injectedHook.onCommitFiberRoot === "function" + ) { + try { + var didError = (root.current.flags & DidCapture) === DidCapture; -function getLaneLabelMap() { - if (enableSchedulingProfiler) { - var map = new Map(); - var lane = 1; + if (enableProfilerTimer) { + var schedulerPriority; - for (var index = 0; index < TotalLanes; index++) { - var label = getLabelForLane(lane); - map.set(lane, label); - lane *= 2; - } + switch (eventPriority) { + case DiscreteEventPriority: + schedulerPriority = ImmediatePriority; + break; - return map; - } else { - return null; - } -} + case ContinuousEventPriority: + schedulerPriority = UserBlockingPriority; + break; -function markCommitStarted(lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markCommitStarted === "function" - ) { - injectedProfilingHooks.markCommitStarted(lanes); - } - } -} -function markCommitStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markCommitStopped === "function" - ) { - injectedProfilingHooks.markCommitStopped(); - } - } -} -function markComponentRenderStarted(fiber) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentRenderStarted === "function" - ) { - injectedProfilingHooks.markComponentRenderStarted(fiber); - } - } -} -function markComponentRenderStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentRenderStopped === "function" - ) { - injectedProfilingHooks.markComponentRenderStopped(); - } - } -} -function markComponentPassiveEffectMountStarted(fiber) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectMountStarted === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectMountStarted(fiber); - } - } -} -function markComponentPassiveEffectMountStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectMountStopped === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectMountStopped(); - } - } -} -function markComponentPassiveEffectUnmountStarted(fiber) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStarted === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectUnmountStarted(fiber); - } - } -} -function markComponentPassiveEffectUnmountStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStopped === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectUnmountStopped(); - } - } -} -function markComponentLayoutEffectMountStarted(fiber) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectMountStarted === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectMountStarted(fiber); - } - } -} -function markComponentLayoutEffectMountStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectMountStopped === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectMountStopped(); - } - } -} -function markComponentLayoutEffectUnmountStarted(fiber) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber); - } - } -} -function markComponentLayoutEffectUnmountStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectUnmountStopped(); - } - } -} -function markComponentErrored(fiber, thrownValue, lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentErrored === "function" - ) { - injectedProfilingHooks.markComponentErrored(fiber, thrownValue, lanes); - } - } -} -function markComponentSuspended(fiber, wakeable, lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentSuspended === "function" - ) { - injectedProfilingHooks.markComponentSuspended(fiber, wakeable, lanes); - } - } -} -function markLayoutEffectsStarted(lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markLayoutEffectsStarted === "function" - ) { - injectedProfilingHooks.markLayoutEffectsStarted(lanes); - } - } -} -function markLayoutEffectsStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markLayoutEffectsStopped === "function" - ) { - injectedProfilingHooks.markLayoutEffectsStopped(); - } - } -} -function markPassiveEffectsStarted(lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markPassiveEffectsStarted === "function" - ) { - injectedProfilingHooks.markPassiveEffectsStarted(lanes); - } - } -} -function markPassiveEffectsStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markPassiveEffectsStopped === "function" - ) { - injectedProfilingHooks.markPassiveEffectsStopped(); - } - } -} -function markRenderStarted(lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderStarted === "function" - ) { - injectedProfilingHooks.markRenderStarted(lanes); - } - } -} -function markRenderYielded() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderYielded === "function" - ) { - injectedProfilingHooks.markRenderYielded(); - } - } -} -function markRenderStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderStopped === "function" - ) { - injectedProfilingHooks.markRenderStopped(); - } - } -} -function markRenderScheduled(lane) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderScheduled === "function" - ) { - injectedProfilingHooks.markRenderScheduled(lane); - } - } -} -function markForceUpdateScheduled(fiber, lane) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markForceUpdateScheduled === "function" - ) { - injectedProfilingHooks.markForceUpdateScheduled(fiber, lane); - } - } -} -function markStateUpdateScheduled(fiber, lane) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markStateUpdateScheduled === "function" - ) { - injectedProfilingHooks.markStateUpdateScheduled(fiber, lane); - } - } -} + case DefaultEventPriority: + schedulerPriority = NormalPriority$1; + break; -var NoMode = - /* */ - 0; // TODO: Remove ConcurrentMode by reading from the root tag instead - -var ConcurrentMode = - /* */ - 1; -var ProfileMode = - /* */ - 2; -var DebugTracingMode = - /* */ - 4; -var StrictLegacyMode = - /* */ - 8; -var StrictEffectsMode = - /* */ - 16; -var ConcurrentUpdatesByDefaultMode = - /* */ - 32; -var NoStrictPassiveEffectsMode = - /* */ - 64; - -// TODO: This is pretty well supported by browsers. Maybe we can drop it. -var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; // Count leading zeros. -// Based on: -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 - -var log$1 = Math.log; -var LN2 = Math.LN2; - -function clz32Fallback(x) { - var asUint = x >>> 0; - - if (asUint === 0) { - return 32; - } - - return (31 - ((log$1(asUint) / LN2) | 0)) | 0; -} + case IdleEventPriority: + schedulerPriority = IdlePriority; + break; -// If those values are changed that package should be rebuilt and redeployed. - -var TotalLanes = 31; -var NoLanes = - /* */ - 0; -var NoLane = - /* */ - 0; -var SyncHydrationLane = - /* */ - 1; -var SyncLane = - /* */ - 2; -var SyncLaneIndex = 1; -var InputContinuousHydrationLane = - /* */ - 4; -var InputContinuousLane = - /* */ - 8; -var DefaultHydrationLane = - /* */ - 16; -var DefaultLane = - /* */ - 32; -var SyncUpdateLanes = enableUnifiedSyncLane - ? SyncLane | InputContinuousLane | DefaultLane - : SyncLane; -var TransitionHydrationLane = - /* */ - 64; -var TransitionLanes = - /* */ - 4194176; -var TransitionLane1 = - /* */ - 128; -var TransitionLane2 = - /* */ - 256; -var TransitionLane3 = - /* */ - 512; -var TransitionLane4 = - /* */ - 1024; -var TransitionLane5 = - /* */ - 2048; -var TransitionLane6 = - /* */ - 4096; -var TransitionLane7 = - /* */ - 8192; -var TransitionLane8 = - /* */ - 16384; -var TransitionLane9 = - /* */ - 32768; -var TransitionLane10 = - /* */ - 65536; -var TransitionLane11 = - /* */ - 131072; -var TransitionLane12 = - /* */ - 262144; -var TransitionLane13 = - /* */ - 524288; -var TransitionLane14 = - /* */ - 1048576; -var TransitionLane15 = - /* */ - 2097152; -var RetryLanes = - /* */ - 62914560; -var RetryLane1 = - /* */ - 4194304; -var RetryLane2 = - /* */ - 8388608; -var RetryLane3 = - /* */ - 16777216; -var RetryLane4 = - /* */ - 33554432; -var SomeRetryLane = RetryLane1; -var SelectiveHydrationLane = - /* */ - 67108864; -var NonIdleLanes = - /* */ - 134217727; -var IdleHydrationLane = - /* */ - 134217728; -var IdleLane = - /* */ - 268435456; -var OffscreenLane = - /* */ - 536870912; -var DeferredLane = - /* */ - 1073741824; // Any lane that might schedule an update. This is used to detect infinite -// update loops, so it doesn't include hydration lanes or retries. - -var UpdateLanes = - SyncLane | InputContinuousLane | DefaultLane | TransitionLanes; // This function is used for the experimental timeline (react-devtools-timeline) -// It should be kept in sync with the Lanes values above. - -function getLabelForLane(lane) { - if (enableSchedulingProfiler) { - if (lane & SyncHydrationLane) { - return "SyncHydrationLane"; - } - - if (lane & SyncLane) { - return "Sync"; - } - - if (lane & InputContinuousHydrationLane) { - return "InputContinuousHydration"; - } - - if (lane & InputContinuousLane) { - return "InputContinuous"; - } - - if (lane & DefaultHydrationLane) { - return "DefaultHydration"; - } - - if (lane & DefaultLane) { - return "Default"; - } - - if (lane & TransitionHydrationLane) { - return "TransitionHydration"; - } - - if (lane & TransitionLanes) { - return "Transition"; - } - - if (lane & RetryLanes) { - return "Retry"; - } - - if (lane & SelectiveHydrationLane) { - return "SelectiveHydration"; - } + default: + schedulerPriority = NormalPriority$1; + break; + } - if (lane & IdleHydrationLane) { - return "IdleHydration"; - } + injectedHook.onCommitFiberRoot( + rendererID, + root, + schedulerPriority, + didError + ); + } + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; - if (lane & IdleLane) { - return "Idle"; + error("React instrumentation encountered an error: %s", err); + } + } + } + } } + function onPostCommitRoot(root) { + if ( + injectedHook && + typeof injectedHook.onPostCommitFiberRoot === "function" + ) { + try { + injectedHook.onPostCommitFiberRoot(rendererID, root); + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; - if (lane & OffscreenLane) { - return "Offscreen"; + error("React instrumentation encountered an error: %s", err); + } + } + } + } } + function onCommitUnmount(fiber) { + if ( + injectedHook && + typeof injectedHook.onCommitFiberUnmount === "function" + ) { + try { + injectedHook.onCommitFiberUnmount(rendererID, fiber); + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; - if (lane & DeferredLane) { - return "Deferred"; + error("React instrumentation encountered an error: %s", err); + } + } + } + } } - } -} -var NoTimestamp = -1; -var nextTransitionLane = TransitionLane1; -var nextRetryLane = RetryLane1; - -function getHighestPriorityLanes(lanes) { - if (enableUnifiedSyncLane) { - var pendingSyncLanes = lanes & SyncUpdateLanes; - - if (pendingSyncLanes !== 0) { - return pendingSyncLanes; - } - } - - switch (getHighestPriorityLane(lanes)) { - case SyncHydrationLane: - return SyncHydrationLane; - - case SyncLane: - return SyncLane; - - case InputContinuousHydrationLane: - return InputContinuousHydrationLane; - - case InputContinuousLane: - return InputContinuousLane; - - case DefaultHydrationLane: - return DefaultHydrationLane; - - case DefaultLane: - return DefaultLane; - - case TransitionHydrationLane: - return TransitionHydrationLane; - - case TransitionLane1: - case TransitionLane2: - case TransitionLane3: - case TransitionLane4: - case TransitionLane5: - case TransitionLane6: - case TransitionLane7: - case TransitionLane8: - case TransitionLane9: - case TransitionLane10: - case TransitionLane11: - case TransitionLane12: - case TransitionLane13: - case TransitionLane14: - case TransitionLane15: - return lanes & TransitionLanes; - - case RetryLane1: - case RetryLane2: - case RetryLane3: - case RetryLane4: - return lanes & RetryLanes; - - case SelectiveHydrationLane: - return SelectiveHydrationLane; - - case IdleHydrationLane: - return IdleHydrationLane; - - case IdleLane: - return IdleLane; - - case OffscreenLane: - return OffscreenLane; - - case DeferredLane: - // This shouldn't be reachable because deferred work is always entangled - // with something else. - return NoLanes; - - default: + function setIsStrictModeForDevtools(newIsStrictMode) { { - error("Should have found matching lanes. This is a bug in React."); - } // This shouldn't be reachable, but as a fallback, return the entire bitmask. - - return lanes; - } -} - -function getNextLanes(root, wipLanes) { - // Early bailout if there's no pending work left. - var pendingLanes = root.pendingLanes; + if (typeof log$2 === "function") { + // We're in a test because Scheduler.log only exists + // in SchedulerMock. To reduce the noise in strict mode tests, + // suppress warnings and disable scheduler yielding during the double render + unstable_setDisableYieldValue(newIsStrictMode); + setSuppressWarning(newIsStrictMode); + } - if (pendingLanes === NoLanes) { - return NoLanes; - } + if (injectedHook && typeof injectedHook.setStrictMode === "function") { + try { + injectedHook.setStrictMode(rendererID, newIsStrictMode); + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; - var nextLanes = NoLanes; - var suspendedLanes = root.suspendedLanes; - var pingedLanes = root.pingedLanes; // Do not work on any idle work until all the non-idle work has finished, - // even if the work is suspended. + error("React instrumentation encountered an error: %s", err); + } + } + } + } + } + } // Profiler API hooks - var nonIdlePendingLanes = pendingLanes & NonIdleLanes; + function injectProfilingHooks(profilingHooks) { + injectedProfilingHooks = profilingHooks; + } - if (nonIdlePendingLanes !== NoLanes) { - var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; + function getLaneLabelMap() { + if (enableSchedulingProfiler) { + var map = new Map(); + var lane = 1; - if (nonIdleUnblockedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); - } else { - var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; + for (var index = 0; index < TotalLanes; index++) { + var label = getLabelForLane(lane); + map.set(lane, label); + lane *= 2; + } - if (nonIdlePingedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); + return map; + } else { + return null; } } - } else { - // The only remaining work is Idle. - var unblockedLanes = pendingLanes & ~suspendedLanes; - if (unblockedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(unblockedLanes); - } else { - if (pingedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(pingedLanes); + function markCommitStarted(lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markCommitStarted === "function" + ) { + injectedProfilingHooks.markCommitStarted(lanes); + } } } - } - - if (nextLanes === NoLanes) { - // This should only be reachable if we're suspended - // TODO: Consider warning in this path if a fallback timer is not scheduled. - return NoLanes; - } // If we're already in the middle of a render, switching lanes will interrupt - // it and we'll lose our progress. We should only do this if the new lanes are - // higher priority. - - if ( - wipLanes !== NoLanes && - wipLanes !== nextLanes && // If we already suspended with a delay, then interrupting is fine. Don't - // bother waiting until the root is complete. - (wipLanes & suspendedLanes) === NoLanes - ) { - var nextLane = getHighestPriorityLane(nextLanes); - var wipLane = getHighestPriorityLane(wipLanes); - - if ( - // Tests whether the next lane is equal or lower priority than the wip - // one. This works because the bits decrease in priority as you go left. - nextLane >= wipLane || // Default priority updates should not interrupt transition updates. The - // only difference between default updates and transition updates is that - // default updates do not support refresh transitions. - (nextLane === DefaultLane && (wipLane & TransitionLanes) !== NoLanes) - ) { - // Keep working on the existing in-progress tree. Do not interrupt. - return wipLanes; + function markCommitStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markCommitStopped === "function" + ) { + injectedProfilingHooks.markCommitStopped(); + } + } } - } - - return nextLanes; -} -function getEntangledLanes(root, renderLanes) { - var entangledLanes = renderLanes; - - if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode); - else if ((entangledLanes & InputContinuousLane) !== NoLanes) { - // When updates are sync by default, we entangle continuous priority updates - // and default updates, so they render in the same batch. The only reason - // they use separate lanes is because continuous updates should interrupt - // transitions, but default updates should not. - entangledLanes |= entangledLanes & DefaultLane; - } // Check for entangled lanes and add them to the batch. - // - // A lane is said to be entangled with another when it's not allowed to render - // in a batch that does not also include the other lane. Typically we do this - // when multiple updates have the same source, and we only want to respond to - // the most recent event from that source. - // - // Note that we apply entanglements *after* checking for partial work above. - // This means that if a lane is entangled during an interleaved event while - // it's already rendering, we won't interrupt it. This is intentional, since - // entanglement is usually "best effort": we'll try our best to render the - // lanes in the same batch, but it's not worth throwing out partially - // completed work in order to do it. - // TODO: Reconsider this. The counter-argument is that the partial work - // represents an intermediate state, which we don't want to show to the user. - // And by spending extra time finishing it, we're increasing the amount of - // time it takes to show the final state, which is what they are actually - // waiting for. - // - // For those exceptions where entanglement is semantically important, - // we should ensure that there is no partial work at the - // time we apply the entanglement. - - var allEntangledLanes = root.entangledLanes; - - if (allEntangledLanes !== NoLanes) { - var entanglements = root.entanglements; - var lanes = entangledLanes & allEntangledLanes; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - entangledLanes |= entanglements[index]; - lanes &= ~lane; - } - } - - return entangledLanes; -} - -function computeExpirationTime(lane, currentTime) { - switch (lane) { - case SyncHydrationLane: - case SyncLane: - case InputContinuousHydrationLane: - case InputContinuousLane: - // User interactions should expire slightly more quickly. - // - // NOTE: This is set to the corresponding constant as in Scheduler.js. - // When we made it larger, a product metric in www regressed, suggesting - // there's a user interaction that's being starved by a series of - // synchronous updates. If that theory is correct, the proper solution is - // to fix the starvation. However, this scenario supports the idea that - // expiration times are an important safeguard when starvation - // does happen. - return currentTime + 250; - - case DefaultHydrationLane: - case DefaultLane: - case TransitionHydrationLane: - case TransitionLane1: - case TransitionLane2: - case TransitionLane3: - case TransitionLane4: - case TransitionLane5: - case TransitionLane6: - case TransitionLane7: - case TransitionLane8: - case TransitionLane9: - case TransitionLane10: - case TransitionLane11: - case TransitionLane12: - case TransitionLane13: - case TransitionLane14: - case TransitionLane15: - return currentTime + 5000; - - case RetryLane1: - case RetryLane2: - case RetryLane3: - case RetryLane4: - // TODO: Retries should be allowed to expire if they are CPU bound for - // too long, but when I made this change it caused a spike in browser - // crashes. There must be some other underlying bug; not super urgent but - // ideally should figure out why and fix it. Unfortunately we don't have - // a repro for the crashes, only detected via production metrics. - return NoTimestamp; - - case SelectiveHydrationLane: - case IdleHydrationLane: - case IdleLane: - case OffscreenLane: - case DeferredLane: - // Anything idle priority or lower should never expire. - return NoTimestamp; - - default: - { - error("Should have found matching lanes. This is a bug in React."); - } - - return NoTimestamp; - } -} - -function markStarvedLanesAsExpired(root, currentTime) { - // TODO: This gets called every time we yield. We can optimize by storing - // the earliest expiration time on the root. Then use that to quickly bail out - // of this function. - var pendingLanes = root.pendingLanes; - var suspendedLanes = root.suspendedLanes; - var pingedLanes = root.pingedLanes; - var expirationTimes = root.expirationTimes; // Iterate through the pending lanes and check if we've reached their - // expiration time. If so, we'll assume the update is being starved and mark - // it as expired to force it to finish. - // TODO: We should be able to replace this with upgradePendingLanesToSync - // - // We exclude retry lanes because those must always be time sliced, in order - // to unwrap uncached promises. - // TODO: Write a test for this - - var lanes = pendingLanes & ~RetryLanes; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - var expirationTime = expirationTimes[index]; - - if (expirationTime === NoTimestamp) { - // Found a pending lane with no expiration time. If it's not suspended, or - // if it's pinged, assume it's CPU-bound. Compute a new expiration time - // using the current time. - if ( - (lane & suspendedLanes) === NoLanes || - (lane & pingedLanes) !== NoLanes - ) { - // Assumes timestamps are monotonically increasing. - expirationTimes[index] = computeExpirationTime(lane, currentTime); + function markComponentRenderStarted(fiber) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentRenderStarted === + "function" + ) { + injectedProfilingHooks.markComponentRenderStarted(fiber); + } } - } else if (expirationTime <= currentTime) { - // This lane expired - root.expiredLanes |= lane; } + function markComponentRenderStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentRenderStopped === + "function" + ) { + injectedProfilingHooks.markComponentRenderStopped(); + } + } + } + function markComponentPassiveEffectMountStarted(fiber) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectMountStarted === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectMountStarted(fiber); + } + } + } + function markComponentPassiveEffectMountStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectMountStopped === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectMountStopped(); + } + } + } + function markComponentPassiveEffectUnmountStarted(fiber) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStarted === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectUnmountStarted( + fiber + ); + } + } + } + function markComponentPassiveEffectUnmountStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStopped === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectUnmountStopped(); + } + } + } + function markComponentLayoutEffectMountStarted(fiber) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectMountStarted === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectMountStarted(fiber); + } + } + } + function markComponentLayoutEffectMountStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectMountStopped === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectMountStopped(); + } + } + } + function markComponentLayoutEffectUnmountStarted(fiber) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber); + } + } + } + function markComponentLayoutEffectUnmountStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectUnmountStopped(); + } + } + } + function markComponentErrored(fiber, thrownValue, lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentErrored === "function" + ) { + injectedProfilingHooks.markComponentErrored( + fiber, + thrownValue, + lanes + ); + } + } + } + function markComponentSuspended(fiber, wakeable, lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentSuspended === "function" + ) { + injectedProfilingHooks.markComponentSuspended(fiber, wakeable, lanes); + } + } + } + function markLayoutEffectsStarted(lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markLayoutEffectsStarted === "function" + ) { + injectedProfilingHooks.markLayoutEffectsStarted(lanes); + } + } + } + function markLayoutEffectsStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markLayoutEffectsStopped === "function" + ) { + injectedProfilingHooks.markLayoutEffectsStopped(); + } + } + } + function markPassiveEffectsStarted(lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markPassiveEffectsStarted === "function" + ) { + injectedProfilingHooks.markPassiveEffectsStarted(lanes); + } + } + } + function markPassiveEffectsStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markPassiveEffectsStopped === "function" + ) { + injectedProfilingHooks.markPassiveEffectsStopped(); + } + } + } + function markRenderStarted(lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderStarted === "function" + ) { + injectedProfilingHooks.markRenderStarted(lanes); + } + } + } + function markRenderYielded() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderYielded === "function" + ) { + injectedProfilingHooks.markRenderYielded(); + } + } + } + function markRenderStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderStopped === "function" + ) { + injectedProfilingHooks.markRenderStopped(); + } + } + } + function markRenderScheduled(lane) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderScheduled === "function" + ) { + injectedProfilingHooks.markRenderScheduled(lane); + } + } + } + function markForceUpdateScheduled(fiber, lane) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markForceUpdateScheduled === "function" + ) { + injectedProfilingHooks.markForceUpdateScheduled(fiber, lane); + } + } + } + function markStateUpdateScheduled(fiber, lane) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markStateUpdateScheduled === "function" + ) { + injectedProfilingHooks.markStateUpdateScheduled(fiber, lane); + } + } + } + + var NoMode = + /* */ + 0; // TODO: Remove ConcurrentMode by reading from the root tag instead + + var ConcurrentMode = + /* */ + 1; + var ProfileMode = + /* */ + 2; + var DebugTracingMode = + /* */ + 4; + var StrictLegacyMode = + /* */ + 8; + var StrictEffectsMode = + /* */ + 16; + var ConcurrentUpdatesByDefaultMode = + /* */ + 32; + var NoStrictPassiveEffectsMode = + /* */ + 64; + + // TODO: This is pretty well supported by browsers. Maybe we can drop it. + var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; // Count leading zeros. + // Based on: + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 + + var log$1 = Math.log; + var LN2 = Math.LN2; + + function clz32Fallback(x) { + var asUint = x >>> 0; + + if (asUint === 0) { + return 32; + } + + return (31 - ((log$1(asUint) / LN2) | 0)) | 0; + } + + // If those values are changed that package should be rebuilt and redeployed. + + var TotalLanes = 31; + var NoLanes = + /* */ + 0; + var NoLane = + /* */ + 0; + var SyncHydrationLane = + /* */ + 1; + var SyncLane = + /* */ + 2; + var SyncLaneIndex = 1; + var InputContinuousHydrationLane = + /* */ + 4; + var InputContinuousLane = + /* */ + 8; + var DefaultHydrationLane = + /* */ + 16; + var DefaultLane = + /* */ + 32; + var SyncUpdateLanes = enableUnifiedSyncLane + ? SyncLane | InputContinuousLane | DefaultLane + : SyncLane; + var TransitionHydrationLane = + /* */ + 64; + var TransitionLanes = + /* */ + 4194176; + var TransitionLane1 = + /* */ + 128; + var TransitionLane2 = + /* */ + 256; + var TransitionLane3 = + /* */ + 512; + var TransitionLane4 = + /* */ + 1024; + var TransitionLane5 = + /* */ + 2048; + var TransitionLane6 = + /* */ + 4096; + var TransitionLane7 = + /* */ + 8192; + var TransitionLane8 = + /* */ + 16384; + var TransitionLane9 = + /* */ + 32768; + var TransitionLane10 = + /* */ + 65536; + var TransitionLane11 = + /* */ + 131072; + var TransitionLane12 = + /* */ + 262144; + var TransitionLane13 = + /* */ + 524288; + var TransitionLane14 = + /* */ + 1048576; + var TransitionLane15 = + /* */ + 2097152; + var RetryLanes = + /* */ + 62914560; + var RetryLane1 = + /* */ + 4194304; + var RetryLane2 = + /* */ + 8388608; + var RetryLane3 = + /* */ + 16777216; + var RetryLane4 = + /* */ + 33554432; + var SomeRetryLane = RetryLane1; + var SelectiveHydrationLane = + /* */ + 67108864; + var NonIdleLanes = + /* */ + 134217727; + var IdleHydrationLane = + /* */ + 134217728; + var IdleLane = + /* */ + 268435456; + var OffscreenLane = + /* */ + 536870912; + var DeferredLane = + /* */ + 1073741824; // Any lane that might schedule an update. This is used to detect infinite + // update loops, so it doesn't include hydration lanes or retries. + + var UpdateLanes = + SyncLane | InputContinuousLane | DefaultLane | TransitionLanes; // This function is used for the experimental timeline (react-devtools-timeline) + // It should be kept in sync with the Lanes values above. + + function getLabelForLane(lane) { + if (enableSchedulingProfiler) { + if (lane & SyncHydrationLane) { + return "SyncHydrationLane"; + } + + if (lane & SyncLane) { + return "Sync"; + } + + if (lane & InputContinuousHydrationLane) { + return "InputContinuousHydration"; + } + + if (lane & InputContinuousLane) { + return "InputContinuous"; + } + + if (lane & DefaultHydrationLane) { + return "DefaultHydration"; + } + + if (lane & DefaultLane) { + return "Default"; + } + + if (lane & TransitionHydrationLane) { + return "TransitionHydration"; + } + + if (lane & TransitionLanes) { + return "Transition"; + } - lanes &= ~lane; - } -} // This returns the highest priority pending lanes regardless of whether they -function getLanesToRetrySynchronouslyOnError(root, originallyAttemptedLanes) { - if (root.errorRecoveryDisabledLanes & originallyAttemptedLanes) { - // The error recovery mechanism is disabled until these lanes are cleared. - return NoLanes; - } - - var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; + if (lane & RetryLanes) { + return "Retry"; + } - if (everythingButOffscreen !== NoLanes) { - return everythingButOffscreen; - } + if (lane & SelectiveHydrationLane) { + return "SelectiveHydration"; + } - if (everythingButOffscreen & OffscreenLane) { - return OffscreenLane; - } + if (lane & IdleHydrationLane) { + return "IdleHydration"; + } - return NoLanes; -} -function includesSyncLane(lanes) { - return (lanes & (SyncLane | SyncHydrationLane)) !== NoLanes; -} -function includesNonIdleWork(lanes) { - return (lanes & NonIdleLanes) !== NoLanes; -} -function includesOnlyRetries(lanes) { - return (lanes & RetryLanes) === lanes; -} -function includesOnlyNonUrgentLanes(lanes) { - // TODO: Should hydration lanes be included here? This function is only - // used in `updateDeferredValueImpl`. - var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; - return (lanes & UrgentLanes) === NoLanes; -} -function includesOnlyTransitions(lanes) { - return (lanes & TransitionLanes) === lanes; -} -function includesBlockingLane(root, lanes) { - if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode) { - // Concurrent updates by default always use time slicing. - return false; - } - - var SyncDefaultLanes = - InputContinuousHydrationLane | - InputContinuousLane | - DefaultHydrationLane | - DefaultLane; - return (lanes & SyncDefaultLanes) !== NoLanes; -} -function includesExpiredLane(root, lanes) { - // This is a separate check from includesBlockingLane because a lane can - // expire after a render has already started. - return (lanes & root.expiredLanes) !== NoLanes; -} -function isTransitionLane(lane) { - return (lane & TransitionLanes) !== NoLanes; -} -function claimNextTransitionLane() { - // Cycle through the lanes, assigning each new transition to the next lane. - // In most cases, this means every transition gets its own lane, until we - // run out of lanes and cycle back to the beginning. - var lane = nextTransitionLane; - nextTransitionLane <<= 1; - - if ((nextTransitionLane & TransitionLanes) === NoLanes) { - nextTransitionLane = TransitionLane1; - } - - return lane; -} -function claimNextRetryLane() { - var lane = nextRetryLane; - nextRetryLane <<= 1; + if (lane & IdleLane) { + return "Idle"; + } - if ((nextRetryLane & RetryLanes) === NoLanes) { - nextRetryLane = RetryLane1; - } + if (lane & OffscreenLane) { + return "Offscreen"; + } - return lane; -} -function getHighestPriorityLane(lanes) { - return lanes & -lanes; -} -function pickArbitraryLane(lanes) { - // This wrapper function gets inlined. Only exists so to communicate that it - // doesn't matter which bit is selected; you can pick any bit without - // affecting the algorithms where its used. Here I'm using - // getHighestPriorityLane because it requires the fewest operations. - return getHighestPriorityLane(lanes); -} + if (lane & DeferredLane) { + return "Deferred"; + } + } + } + var NoTimestamp = -1; + var nextTransitionLane = TransitionLane1; + var nextRetryLane = RetryLane1; -function pickArbitraryLaneIndex(lanes) { - return 31 - clz32(lanes); -} + function getHighestPriorityLanes(lanes) { + if (enableUnifiedSyncLane) { + var pendingSyncLanes = lanes & SyncUpdateLanes; -function laneToIndex(lane) { - return pickArbitraryLaneIndex(lane); -} + if (pendingSyncLanes !== 0) { + return pendingSyncLanes; + } + } -function includesSomeLane(a, b) { - return (a & b) !== NoLanes; -} -function isSubsetOfLanes(set, subset) { - return (set & subset) === subset; -} -function mergeLanes(a, b) { - return a | b; -} -function removeLanes(set, subset) { - return set & ~subset; -} -function intersectLanes(a, b) { - return a & b; -} // Seems redundant, but it changes the type from a single lane (used for -// updates) to a group of lanes (used for flushing work). + switch (getHighestPriorityLane(lanes)) { + case SyncHydrationLane: + return SyncHydrationLane; -function laneToLanes(lane) { - return lane; -} -function createLaneMap(initial) { - // Intentionally pushing one by one. - // https://v8.dev/blog/elements-kinds#avoid-creating-holes - var laneMap = []; + case SyncLane: + return SyncLane; - for (var i = 0; i < TotalLanes; i++) { - laneMap.push(initial); - } + case InputContinuousHydrationLane: + return InputContinuousHydrationLane; - return laneMap; -} -function markRootUpdated(root, updateLane) { - root.pendingLanes |= updateLane; // If there are any suspended transitions, it's possible this new update - // could unblock them. Clear the suspended lanes so that we can try rendering - // them again. - // - // TODO: We really only need to unsuspend only lanes that are in the - // `subtreeLanes` of the updated fiber, or the update lanes of the return - // path. This would exclude suspended updates in an unrelated sibling tree, - // since there's no way for this update to unblock it. - // - // We don't do this if the incoming update is idle, because we never process - // idle updates until after all the regular updates have finished; there's no - // way it could unblock a transition. - - if (updateLane !== IdleLane) { - root.suspendedLanes = NoLanes; - root.pingedLanes = NoLanes; - } -} -function markRootSuspended$1(root, suspendedLanes, spawnedLane) { - root.suspendedLanes |= suspendedLanes; - root.pingedLanes &= ~suspendedLanes; // The suspended lanes are no longer CPU-bound. Clear their expiration times. - - var expirationTimes = root.expirationTimes; - var lanes = suspendedLanes; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - expirationTimes[index] = NoTimestamp; - lanes &= ~lane; - } - - if (spawnedLane !== NoLane) { - markSpawnedDeferredLane(root, spawnedLane, suspendedLanes); - } -} -function markRootPinged(root, pingedLanes) { - root.pingedLanes |= root.suspendedLanes & pingedLanes; -} -function markRootFinished(root, remainingLanes, spawnedLane) { - var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; - root.pendingLanes = remainingLanes; // Let's try everything again + case InputContinuousLane: + return InputContinuousLane; - root.suspendedLanes = NoLanes; - root.pingedLanes = NoLanes; - root.expiredLanes &= remainingLanes; - root.entangledLanes &= remainingLanes; - root.errorRecoveryDisabledLanes &= remainingLanes; - root.shellSuspendCounter = 0; - var entanglements = root.entanglements; - var expirationTimes = root.expirationTimes; - var hiddenUpdates = root.hiddenUpdates; // Clear the lanes that no longer have pending work + case DefaultHydrationLane: + return DefaultHydrationLane; - var lanes = noLongerPendingLanes; + case DefaultLane: + return DefaultLane; - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - entanglements[index] = NoLanes; - expirationTimes[index] = NoTimestamp; - var hiddenUpdatesForLane = hiddenUpdates[index]; + case TransitionHydrationLane: + return TransitionHydrationLane; - if (hiddenUpdatesForLane !== null) { - hiddenUpdates[index] = null; // "Hidden" updates are updates that were made to a hidden component. They - // have special logic associated with them because they may be entangled - // with updates that occur outside that tree. But once the outer tree - // commits, they behave like regular updates. + case TransitionLane1: + case TransitionLane2: + case TransitionLane3: + case TransitionLane4: + case TransitionLane5: + case TransitionLane6: + case TransitionLane7: + case TransitionLane8: + case TransitionLane9: + case TransitionLane10: + case TransitionLane11: + case TransitionLane12: + case TransitionLane13: + case TransitionLane14: + case TransitionLane15: + return lanes & TransitionLanes; - for (var i = 0; i < hiddenUpdatesForLane.length; i++) { - var update = hiddenUpdatesForLane[i]; + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + return lanes & RetryLanes; - if (update !== null) { - update.lane &= ~OffscreenLane; - } - } - } + case SelectiveHydrationLane: + return SelectiveHydrationLane; - lanes &= ~lane; - } + case IdleHydrationLane: + return IdleHydrationLane; - if (spawnedLane !== NoLane) { - markSpawnedDeferredLane( - root, - spawnedLane, // This render finished successfully without suspending, so we don't need - // to entangle the spawned task with the parent task. - NoLanes - ); - } -} + case IdleLane: + return IdleLane; -function markSpawnedDeferredLane(root, spawnedLane, entangledLanes) { - // This render spawned a deferred task. Mark it as pending. - root.pendingLanes |= spawnedLane; - root.suspendedLanes &= ~spawnedLane; // Entangle the spawned lane with the DeferredLane bit so that we know it - // was the result of another render. This lets us avoid a useDeferredValue - // waterfall — only the first level will defer. - - var spawnedLaneIndex = laneToIndex(spawnedLane); - root.entangledLanes |= spawnedLane; - root.entanglements[spawnedLaneIndex] |= - DeferredLane | // If the parent render task suspended, we must also entangle those lanes - // with the spawned task, so that the deferred task includes all the same - // updates that the parent task did. We can exclude any lane that is not - // used for updates (e.g. Offscreen). - (entangledLanes & UpdateLanes); -} + case OffscreenLane: + return OffscreenLane; -function markRootEntangled(root, entangledLanes) { - // In addition to entangling each of the given lanes with each other, we also - // have to consider _transitive_ entanglements. For each lane that is already - // entangled with *any* of the given lanes, that lane is now transitively - // entangled with *all* the given lanes. - // - // Translated: If C is entangled with A, then entangling A with B also - // entangles C with B. - // - // If this is hard to grasp, it might help to intentionally break this - // function and look at the tests that fail in ReactTransition-test.js. Try - // commenting out one of the conditions below. - var rootEntangledLanes = (root.entangledLanes |= entangledLanes); - var entanglements = root.entanglements; - var lanes = rootEntangledLanes; - - while (lanes) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; + case DeferredLane: + // This shouldn't be reachable because deferred work is always entangled + // with something else. + return NoLanes; - if ( - // Is this one of the newly entangled lanes? - (lane & entangledLanes) | // Is this lane transitively entangled with the newly entangled lanes? - (entanglements[index] & entangledLanes) - ) { - entanglements[index] |= entangledLanes; + default: + { + error("Should have found matching lanes. This is a bug in React."); + } // This shouldn't be reachable, but as a fallback, return the entire bitmask. + + return lanes; + } } - lanes &= ~lane; - } -} -function upgradePendingLaneToSync(root, lane) { - // Since we're upgrading the priority of the given lane, there is now pending - // sync work. - root.pendingLanes |= SyncLane; // Entangle the sync lane with the lane we're upgrading. This means SyncLane - // will not be allowed to finish without also finishing the given lane. - - root.entangledLanes |= SyncLane; - root.entanglements[SyncLaneIndex] |= lane; -} -function markHiddenUpdate(root, update, lane) { - var index = laneToIndex(lane); - var hiddenUpdates = root.hiddenUpdates; - var hiddenUpdatesForLane = hiddenUpdates[index]; - - if (hiddenUpdatesForLane === null) { - hiddenUpdates[index] = [update]; - } else { - hiddenUpdatesForLane.push(update); - } - - update.lane = lane | OffscreenLane; -} -function getBumpedLaneForHydration(root, renderLanes) { - var renderLane = getHighestPriorityLane(renderLanes); - var lane; - - if (enableUnifiedSyncLane && (renderLane & SyncUpdateLanes) !== NoLane) { - lane = SyncHydrationLane; - } else { - switch (renderLane) { - case SyncLane: - lane = SyncHydrationLane; - break; - - case InputContinuousLane: - lane = InputContinuousHydrationLane; - break; - - case DefaultLane: - lane = DefaultHydrationLane; - break; - - case TransitionLane1: - case TransitionLane2: - case TransitionLane3: - case TransitionLane4: - case TransitionLane5: - case TransitionLane6: - case TransitionLane7: - case TransitionLane8: - case TransitionLane9: - case TransitionLane10: - case TransitionLane11: - case TransitionLane12: - case TransitionLane13: - case TransitionLane14: - case TransitionLane15: - case RetryLane1: - case RetryLane2: - case RetryLane3: - case RetryLane4: - lane = TransitionHydrationLane; - break; - - case IdleLane: - lane = IdleHydrationLane; - break; - - default: - // Everything else is already either a hydration lane, or shouldn't - // be retried at a hydration lane. - lane = NoLane; - break; - } - } // Check if the lane we chose is suspended. If so, that indicates that we - // already attempted and failed to hydrate at that level. Also check if we're - // already rendering that lane, which is rare but could happen. - - if ((lane & (root.suspendedLanes | renderLanes)) !== NoLane) { - // Give up trying to hydrate and fall back to client render. - return NoLane; - } - - return lane; -} -function addFiberToLanesMap(root, fiber, lanes) { - if (!isDevToolsPresent) { - return; - } - - var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; - - while (lanes > 0) { - var index = laneToIndex(lanes); - var lane = 1 << index; - var updaters = pendingUpdatersLaneMap[index]; - updaters.add(fiber); - lanes &= ~lane; - } -} -function movePendingFibersToMemoized(root, lanes) { - if (!isDevToolsPresent) { - return; - } + function getNextLanes(root, wipLanes) { + // Early bailout if there's no pending work left. + var pendingLanes = root.pendingLanes; - var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; - var memoizedUpdaters = root.memoizedUpdaters; + if (pendingLanes === NoLanes) { + return NoLanes; + } - while (lanes > 0) { - var index = laneToIndex(lanes); - var lane = 1 << index; - var updaters = pendingUpdatersLaneMap[index]; + var nextLanes = NoLanes; + var suspendedLanes = root.suspendedLanes; + var pingedLanes = root.pingedLanes; // Do not work on any idle work until all the non-idle work has finished, + // even if the work is suspended. - if (updaters.size > 0) { - updaters.forEach(function (fiber) { - var alternate = fiber.alternate; + var nonIdlePendingLanes = pendingLanes & NonIdleLanes; - if (alternate === null || !memoizedUpdaters.has(alternate)) { - memoizedUpdaters.add(fiber); - } - }); - updaters.clear(); - } + if (nonIdlePendingLanes !== NoLanes) { + var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; - lanes &= ~lane; - } -} -function addTransitionToLanesMap(root, transition, lane) { - if (enableTransitionTracing) { - var transitionLanesMap = root.transitionLanes; - var index = laneToIndex(lane); - var transitions = transitionLanesMap[index]; + if (nonIdleUnblockedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); + } else { + var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; - if (transitions === null) { - transitions = new Set(); - } + if (nonIdlePingedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); + } + } + } else { + // The only remaining work is Idle. + var unblockedLanes = pendingLanes & ~suspendedLanes; - transitions.add(transition); - transitionLanesMap[index] = transitions; - } -} -function getTransitionsForLanes(root, lanes) { - if (!enableTransitionTracing) { - return null; - } + if (unblockedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(unblockedLanes); + } else { + if (pingedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(pingedLanes); + } + } + } - var transitionsForLanes = []; + if (nextLanes === NoLanes) { + // This should only be reachable if we're suspended + // TODO: Consider warning in this path if a fallback timer is not scheduled. + return NoLanes; + } // If we're already in the middle of a render, switching lanes will interrupt + // it and we'll lose our progress. We should only do this if the new lanes are + // higher priority. + + if ( + wipLanes !== NoLanes && + wipLanes !== nextLanes && // If we already suspended with a delay, then interrupting is fine. Don't + // bother waiting until the root is complete. + (wipLanes & suspendedLanes) === NoLanes + ) { + var nextLane = getHighestPriorityLane(nextLanes); + var wipLane = getHighestPriorityLane(wipLanes); - while (lanes > 0) { - var index = laneToIndex(lanes); - var lane = 1 << index; - var transitions = root.transitionLanes[index]; + if ( + // Tests whether the next lane is equal or lower priority than the wip + // one. This works because the bits decrease in priority as you go left. + nextLane >= wipLane || // Default priority updates should not interrupt transition updates. The + // only difference between default updates and transition updates is that + // default updates do not support refresh transitions. + (nextLane === DefaultLane && (wipLane & TransitionLanes) !== NoLanes) + ) { + // Keep working on the existing in-progress tree. Do not interrupt. + return wipLanes; + } + } - if (transitions !== null) { - transitions.forEach(function (transition) { - transitionsForLanes.push(transition); - }); + return nextLanes; } + function getEntangledLanes(root, renderLanes) { + var entangledLanes = renderLanes; - lanes &= ~lane; - } + if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode); + else if ((entangledLanes & InputContinuousLane) !== NoLanes) { + // When updates are sync by default, we entangle continuous priority updates + // and default updates, so they render in the same batch. The only reason + // they use separate lanes is because continuous updates should interrupt + // transitions, but default updates should not. + entangledLanes |= entangledLanes & DefaultLane; + } // Check for entangled lanes and add them to the batch. + // + // A lane is said to be entangled with another when it's not allowed to render + // in a batch that does not also include the other lane. Typically we do this + // when multiple updates have the same source, and we only want to respond to + // the most recent event from that source. + // + // Note that we apply entanglements *after* checking for partial work above. + // This means that if a lane is entangled during an interleaved event while + // it's already rendering, we won't interrupt it. This is intentional, since + // entanglement is usually "best effort": we'll try our best to render the + // lanes in the same batch, but it's not worth throwing out partially + // completed work in order to do it. + // TODO: Reconsider this. The counter-argument is that the partial work + // represents an intermediate state, which we don't want to show to the user. + // And by spending extra time finishing it, we're increasing the amount of + // time it takes to show the final state, which is what they are actually + // waiting for. + // + // For those exceptions where entanglement is semantically important, + // we should ensure that there is no partial work at the + // time we apply the entanglement. - if (transitionsForLanes.length === 0) { - return null; - } + var allEntangledLanes = root.entangledLanes; - return transitionsForLanes; -} -function clearTransitionsForLanes(root, lanes) { - if (!enableTransitionTracing) { - return; - } + if (allEntangledLanes !== NoLanes) { + var entanglements = root.entanglements; + var lanes = entangledLanes & allEntangledLanes; - while (lanes > 0) { - var index = laneToIndex(lanes); - var lane = 1 << index; - var transitions = root.transitionLanes[index]; + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + entangledLanes |= entanglements[index]; + lanes &= ~lane; + } + } - if (transitions !== null) { - root.transitionLanes[index] = null; + return entangledLanes; } - lanes &= ~lane; - } -} + function computeExpirationTime(lane, currentTime) { + switch (lane) { + case SyncHydrationLane: + case SyncLane: + case InputContinuousHydrationLane: + case InputContinuousLane: + // User interactions should expire slightly more quickly. + // + // NOTE: This is set to the corresponding constant as in Scheduler.js. + // When we made it larger, a product metric in www regressed, suggesting + // there's a user interaction that's being starved by a series of + // synchronous updates. If that theory is correct, the proper solution is + // to fix the starvation. However, this scenario supports the idea that + // expiration times are an important safeguard when starvation + // does happen. + return currentTime + 250; + + case DefaultHydrationLane: + case DefaultLane: + case TransitionHydrationLane: + case TransitionLane1: + case TransitionLane2: + case TransitionLane3: + case TransitionLane4: + case TransitionLane5: + case TransitionLane6: + case TransitionLane7: + case TransitionLane8: + case TransitionLane9: + case TransitionLane10: + case TransitionLane11: + case TransitionLane12: + case TransitionLane13: + case TransitionLane14: + case TransitionLane15: + return currentTime + 5000; + + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + // TODO: Retries should be allowed to expire if they are CPU bound for + // too long, but when I made this change it caused a spike in browser + // crashes. There must be some other underlying bug; not super urgent but + // ideally should figure out why and fix it. Unfortunately we don't have + // a repro for the crashes, only detected via production metrics. + return NoTimestamp; + + case SelectiveHydrationLane: + case IdleHydrationLane: + case IdleLane: + case OffscreenLane: + case DeferredLane: + // Anything idle priority or lower should never expire. + return NoTimestamp; + + default: + { + error("Should have found matching lanes. This is a bug in React."); + } -var DiscreteEventPriority = SyncLane; -var ContinuousEventPriority = InputContinuousLane; -var DefaultEventPriority = DefaultLane; -var IdleEventPriority = IdleLane; -var currentUpdatePriority = NoLane; -function getCurrentUpdatePriority() { - return currentUpdatePriority; -} -function setCurrentUpdatePriority(newPriority) { - currentUpdatePriority = newPriority; -} -function higherEventPriority(a, b) { - return a !== 0 && a < b ? a : b; -} -function lowerEventPriority(a, b) { - return a === 0 || a > b ? a : b; -} -function isHigherEventPriority(a, b) { - return a !== 0 && a < b; -} -function lanesToEventPriority(lanes) { - var lane = getHighestPriorityLane(lanes); + return NoTimestamp; + } + } - if (!isHigherEventPriority(DiscreteEventPriority, lane)) { - return DiscreteEventPriority; - } + function markStarvedLanesAsExpired(root, currentTime) { + // TODO: This gets called every time we yield. We can optimize by storing + // the earliest expiration time on the root. Then use that to quickly bail out + // of this function. + var pendingLanes = root.pendingLanes; + var suspendedLanes = root.suspendedLanes; + var pingedLanes = root.pingedLanes; + var expirationTimes = root.expirationTimes; // Iterate through the pending lanes and check if we've reached their + // expiration time. If so, we'll assume the update is being starved and mark + // it as expired to force it to finish. + // TODO: We should be able to replace this with upgradePendingLanesToSync + // + // We exclude retry lanes because those must always be time sliced, in order + // to unwrap uncached promises. + // TODO: Write a test for this - if (!isHigherEventPriority(ContinuousEventPriority, lane)) { - return ContinuousEventPriority; - } + var lanes = pendingLanes & ~RetryLanes; - if (includesNonIdleWork(lane)) { - return DefaultEventPriority; - } + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + var expirationTime = expirationTimes[index]; - return IdleEventPriority; -} + if (expirationTime === NoTimestamp) { + // Found a pending lane with no expiration time. If it's not suspended, or + // if it's pinged, assume it's CPU-bound. Compute a new expiration time + // using the current time. + if ( + (lane & suspendedLanes) === NoLanes || + (lane & pingedLanes) !== NoLanes + ) { + // Assumes timestamps are monotonically increasing. + expirationTimes[index] = computeExpirationTime(lane, currentTime); + } + } else if (expirationTime <= currentTime) { + // This lane expired + root.expiredLanes |= lane; + } -// Renderers that don't support hydration -// can re-export everything from this module. -function shim$2() { - throw new Error( - "The current renderer does not support hydration. " + - "This error is likely caused by a bug in React. " + - "Please file an issue." - ); -} // Hydration (when unsupported) -var isSuspenseInstancePending = shim$2; -var isSuspenseInstanceFallback = shim$2; -var getSuspenseInstanceFallbackErrorDetails = shim$2; -var registerSuspenseInstanceRetry = shim$2; -var clearSuspenseBoundary = shim$2; -var clearSuspenseBoundaryFromContainer = shim$2; -var errorHydratingContainer = shim$2; - -// Renderers that don't support React Scopes -// can re-export everything from this module. -function shim$1() { - throw new Error( - "The current renderer does not support React Scopes. " + - "This error is likely caused by a bug in React. " + - "Please file an issue." - ); -} // React Scopes (when unsupported) - -var prepareScopeUpdate = shim$1; -var getInstanceFromScope = shim$1; - -// Renderers that don't support hydration -// can re-export everything from this module. -function shim() { - throw new Error( - "The current renderer does not support Resources. " + - "This error is likely caused by a bug in React. " + - "Please file an issue." - ); -} // Resources (when unsupported) -var suspendResource = shim; - -var pooledTransform = new Transform(); -var NO_CONTEXT = {}; - -{ - Object.freeze(NO_CONTEXT); -} -/** Helper Methods */ + lanes &= ~lane; + } + } // This returns the highest priority pending lanes regardless of whether they + function getLanesToRetrySynchronouslyOnError( + root, + originallyAttemptedLanes + ) { + if (root.errorRecoveryDisabledLanes & originallyAttemptedLanes) { + // The error recovery mechanism is disabled until these lanes are cleared. + return NoLanes; + } -function addEventListeners(instance, type, listener) { - // We need to explicitly unregister before unmount. - // For this reason we need to track subscriptions. - if (!instance._listeners) { - instance._listeners = {}; - instance._subscriptions = {}; - } + var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; - instance._listeners[type] = listener; + if (everythingButOffscreen !== NoLanes) { + return everythingButOffscreen; + } - if (listener) { - if (!instance._subscriptions[type]) { - instance._subscriptions[type] = instance.subscribe( - type, - createEventHandler(instance), - instance - ); + if (everythingButOffscreen & OffscreenLane) { + return OffscreenLane; + } + + return NoLanes; + } + function includesSyncLane(lanes) { + return (lanes & (SyncLane | SyncHydrationLane)) !== NoLanes; + } + function includesNonIdleWork(lanes) { + return (lanes & NonIdleLanes) !== NoLanes; } - } else { - if (instance._subscriptions[type]) { - instance._subscriptions[type](); + function includesOnlyRetries(lanes) { + return (lanes & RetryLanes) === lanes; + } + function includesOnlyNonUrgentLanes(lanes) { + // TODO: Should hydration lanes be included here? This function is only + // used in `updateDeferredValueImpl`. + var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; + return (lanes & UrgentLanes) === NoLanes; + } + function includesOnlyTransitions(lanes) { + return (lanes & TransitionLanes) === lanes; + } + function includesBlockingLane(root, lanes) { + if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode) { + // Concurrent updates by default always use time slicing. + return false; + } - delete instance._subscriptions[type]; + var SyncDefaultLanes = + InputContinuousHydrationLane | + InputContinuousLane | + DefaultHydrationLane | + DefaultLane; + return (lanes & SyncDefaultLanes) !== NoLanes; } - } -} + function includesExpiredLane(root, lanes) { + // This is a separate check from includesBlockingLane because a lane can + // expire after a render has already started. + return (lanes & root.expiredLanes) !== NoLanes; + } + function isTransitionLane(lane) { + return (lane & TransitionLanes) !== NoLanes; + } + function claimNextTransitionLane() { + // Cycle through the lanes, assigning each new transition to the next lane. + // In most cases, this means every transition gets its own lane, until we + // run out of lanes and cycle back to the beginning. + var lane = nextTransitionLane; + nextTransitionLane <<= 1; -function createEventHandler(instance) { - return function handleEvent(event) { - var listener = instance._listeners[event.type]; + if ((nextTransitionLane & TransitionLanes) === NoLanes) { + nextTransitionLane = TransitionLane1; + } - if (!listener); - else if (typeof listener === "function") { - listener.call(instance, event); - } else if (listener.handleEvent) { - listener.handleEvent(event); + return lane; } - }; -} + function claimNextRetryLane() { + var lane = nextRetryLane; + nextRetryLane <<= 1; + + if ((nextRetryLane & RetryLanes) === NoLanes) { + nextRetryLane = RetryLane1; + } -function destroyEventListeners(instance) { - if (instance._subscriptions) { - for (var type in instance._subscriptions) { - instance._subscriptions[type](); + return lane; + } + function getHighestPriorityLane(lanes) { + return lanes & -lanes; + } + function pickArbitraryLane(lanes) { + // This wrapper function gets inlined. Only exists so to communicate that it + // doesn't matter which bit is selected; you can pick any bit without + // affecting the algorithms where its used. Here I'm using + // getHighestPriorityLane because it requires the fewest operations. + return getHighestPriorityLane(lanes); } - } - instance._subscriptions = null; - instance._listeners = null; -} + function pickArbitraryLaneIndex(lanes) { + return 31 - clz32(lanes); + } -function getScaleX(props) { - if (props.scaleX != null) { - return props.scaleX; - } else if (props.scale != null) { - return props.scale; - } else { - return 1; - } -} + function laneToIndex(lane) { + return pickArbitraryLaneIndex(lane); + } -function getScaleY(props) { - if (props.scaleY != null) { - return props.scaleY; - } else if (props.scale != null) { - return props.scale; - } else { - return 1; - } -} + function includesSomeLane(a, b) { + return (a & b) !== NoLanes; + } + function isSubsetOfLanes(set, subset) { + return (set & subset) === subset; + } + function mergeLanes(a, b) { + return a | b; + } + function removeLanes(set, subset) { + return set & ~subset; + } + function intersectLanes(a, b) { + return a & b; + } // Seems redundant, but it changes the type from a single lane (used for + // updates) to a group of lanes (used for flushing work). -function isSameFont(oldFont, newFont) { - if (oldFont === newFont) { - return true; - } else if (typeof newFont === "string" || typeof oldFont === "string") { - return false; - } else { - return ( - newFont.fontSize === oldFont.fontSize && - newFont.fontStyle === oldFont.fontStyle && - newFont.fontVariant === oldFont.fontVariant && - newFont.fontWeight === oldFont.fontWeight && - newFont.fontFamily === oldFont.fontFamily - ); - } -} -/** Render Methods */ - -function applyClippingRectangleProps(instance, props) { - var prevProps = - arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - applyNodeProps(instance, props, prevProps); - instance.width = props.width; - instance.height = props.height; -} + function laneToLanes(lane) { + return lane; + } + function createLaneMap(initial) { + // Intentionally pushing one by one. + // https://v8.dev/blog/elements-kinds#avoid-creating-holes + var laneMap = []; -function applyGroupProps(instance, props) { - var prevProps = - arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - applyNodeProps(instance, props, prevProps); - instance.width = props.width; - instance.height = props.height; -} + for (var i = 0; i < TotalLanes; i++) { + laneMap.push(initial); + } -function applyNodeProps(instance, props) { - var prevProps = - arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - var scaleX = getScaleX(props); - var scaleY = getScaleY(props); - pooledTransform - .transformTo(1, 0, 0, 1, 0, 0) - .move(props.x || 0, props.y || 0) - .rotate(props.rotation || 0, props.originX, props.originY) - .scale(scaleX, scaleY, props.originX, props.originY); - - if (props.transform != null) { - pooledTransform.transform(props.transform); - } - - if ( - instance.xx !== pooledTransform.xx || - instance.yx !== pooledTransform.yx || - instance.xy !== pooledTransform.xy || - instance.yy !== pooledTransform.yy || - instance.x !== pooledTransform.x || - instance.y !== pooledTransform.y - ) { - instance.transformTo(pooledTransform); - } - - if (props.cursor !== prevProps.cursor || props.title !== prevProps.title) { - instance.indicate(props.cursor, props.title); - } - - if (instance.blend && props.opacity !== prevProps.opacity) { - instance.blend(props.opacity == null ? 1 : props.opacity); - } - - if (props.visible !== prevProps.visible) { - if (props.visible == null || props.visible) { - instance.show(); - } else { - instance.hide(); + return laneMap; } - } + function markRootUpdated(root, updateLane) { + root.pendingLanes |= updateLane; // If there are any suspended transitions, it's possible this new update + // could unblock them. Clear the suspended lanes so that we can try rendering + // them again. + // + // TODO: We really only need to unsuspend only lanes that are in the + // `subtreeLanes` of the updated fiber, or the update lanes of the return + // path. This would exclude suspended updates in an unrelated sibling tree, + // since there's no way for this update to unblock it. + // + // We don't do this if the incoming update is idle, because we never process + // idle updates until after all the regular updates have finished; there's no + // way it could unblock a transition. - for (var type in EVENT_TYPES) { - addEventListeners(instance, EVENT_TYPES[type], props[type]); - } -} + if (updateLane !== IdleLane) { + root.suspendedLanes = NoLanes; + root.pingedLanes = NoLanes; + } + } + function markRootSuspended$1(root, suspendedLanes, spawnedLane) { + root.suspendedLanes |= suspendedLanes; + root.pingedLanes &= ~suspendedLanes; // The suspended lanes are no longer CPU-bound. Clear their expiration times. -function applyRenderableNodeProps(instance, props) { - var prevProps = - arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - applyNodeProps(instance, props, prevProps); + var expirationTimes = root.expirationTimes; + var lanes = suspendedLanes; - if (prevProps.fill !== props.fill) { - if (props.fill && props.fill.applyFill) { - props.fill.applyFill(instance); - } else { - instance.fill(props.fill); - } - } - - if ( - prevProps.stroke !== props.stroke || - prevProps.strokeWidth !== props.strokeWidth || - prevProps.strokeCap !== props.strokeCap || - prevProps.strokeJoin !== props.strokeJoin || // TODO: Consider deep check of stokeDash; may benefit VML in IE. - prevProps.strokeDash !== props.strokeDash - ) { - instance.stroke( - props.stroke, - props.strokeWidth, - props.strokeCap, - props.strokeJoin, - props.strokeDash - ); - } -} - -function applyShapeProps(instance, props) { - var prevProps = - arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - applyRenderableNodeProps(instance, props, prevProps); - var path = props.d || childrenAsString(props.children); - var prevDelta = instance._prevDelta; - var prevPath = instance._prevPath; - - if ( - path !== prevPath || - path.delta !== prevDelta || - prevProps.height !== props.height || - prevProps.width !== props.width - ) { - instance.draw(path, props.width, props.height); - instance._prevDelta = path.delta; - instance._prevPath = path; - } -} - -function applyTextProps(instance, props) { - var prevProps = - arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - applyRenderableNodeProps(instance, props, prevProps); - var string = props.children; - - if ( - instance._currentString !== string || - !isSameFont(props.font, prevProps.font) || - props.alignment !== prevProps.alignment || - props.path !== prevProps.path - ) { - instance.draw(string, props.font, props.alignment, props.path); - instance._currentString = string; - } -} -function appendInitialChild(parentInstance, child) { - if (typeof child === "string") { - // Noop for string children of Text (eg {'foo'}{'bar'}) - throw new Error("Text children should already be flattened."); - } - - child.inject(parentInstance); -} -function createInstance(type, props, internalInstanceHandle) { - var instance; - - switch (type) { - case TYPES.CLIPPING_RECTANGLE: - instance = Mode$1.ClippingRectangle(); - instance._applyProps = applyClippingRectangleProps; - break; - - case TYPES.GROUP: - instance = Mode$1.Group(); - instance._applyProps = applyGroupProps; - break; - - case TYPES.SHAPE: - instance = Mode$1.Shape(); - instance._applyProps = applyShapeProps; - break; - - case TYPES.TEXT: - instance = Mode$1.Text( - props.children, - props.font, - props.alignment, - props.path - ); - instance._applyProps = applyTextProps; - break; - } - - if (!instance) { - throw new Error('ReactART does not support the type "' + type + '"'); - } + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + expirationTimes[index] = NoTimestamp; + lanes &= ~lane; + } - instance._applyProps(instance, props); + if (spawnedLane !== NoLane) { + markSpawnedDeferredLane(root, spawnedLane, suspendedLanes); + } + } + function markRootPinged(root, pingedLanes) { + root.pingedLanes |= root.suspendedLanes & pingedLanes; + } + function markRootFinished(root, remainingLanes, spawnedLane) { + var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; + root.pendingLanes = remainingLanes; // Let's try everything again - return instance; -} -function createTextInstance( - text, - rootContainerInstance, - internalInstanceHandle -) { - return text; -} -function getPublicInstance(instance) { - return instance; -} -function prepareForCommit() { - // Noop - return null; -} -function resetTextContent(domElement) { - // Noop -} -function getRootHostContext() { - return NO_CONTEXT; -} -function getChildHostContext() { - return NO_CONTEXT; -} -var scheduleTimeout = setTimeout; -var cancelTimeout = clearTimeout; -var noTimeout = -1; -function shouldSetTextContent(type, props) { - return ( - typeof props.children === "string" || typeof props.children === "number" - ); -} -function getCurrentEventPriority() { - return DefaultEventPriority; -} -function shouldAttemptEagerTransition() { - return false; -} // The ART renderer is secondary to the React DOM renderer. + root.suspendedLanes = NoLanes; + root.pingedLanes = NoLanes; + root.expiredLanes &= remainingLanes; + root.entangledLanes &= remainingLanes; + root.errorRecoveryDisabledLanes &= remainingLanes; + root.shellSuspendCounter = 0; + var entanglements = root.entanglements; + var expirationTimes = root.expirationTimes; + var hiddenUpdates = root.hiddenUpdates; // Clear the lanes that no longer have pending work -var warnsIfNotActing = false; -function appendChild(parentInstance, child) { - if (child.parentNode === parentInstance) { - child.eject(); - } + var lanes = noLongerPendingLanes; - child.inject(parentInstance); -} -function appendChildToContainer(parentInstance, child) { - if (child.parentNode === parentInstance) { - child.eject(); - } + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + entanglements[index] = NoLanes; + expirationTimes[index] = NoTimestamp; + var hiddenUpdatesForLane = hiddenUpdates[index]; - child.inject(parentInstance); -} -function insertBefore(parentInstance, child, beforeChild) { - if (child === beforeChild) { - throw new Error("ReactART: Can not insert node before itself"); - } + if (hiddenUpdatesForLane !== null) { + hiddenUpdates[index] = null; // "Hidden" updates are updates that were made to a hidden component. They + // have special logic associated with them because they may be entangled + // with updates that occur outside that tree. But once the outer tree + // commits, they behave like regular updates. - child.injectBefore(beforeChild); -} -function insertInContainerBefore(parentInstance, child, beforeChild) { - if (child === beforeChild) { - throw new Error("ReactART: Can not insert node before itself"); - } + for (var i = 0; i < hiddenUpdatesForLane.length; i++) { + var update = hiddenUpdatesForLane[i]; - child.injectBefore(beforeChild); -} -function removeChild(parentInstance, child) { - destroyEventListeners(child); - child.eject(); -} -function removeChildFromContainer(parentInstance, child) { - destroyEventListeners(child); - child.eject(); -} -function commitTextUpdate(textInstance, oldText, newText) { - // Noop -} -function commitMount(instance, type, newProps) { - // Noop -} -function commitUpdate(instance, updatePayload, type, oldProps, newProps) { - instance._applyProps(instance, newProps, oldProps); -} -function hideInstance(instance) { - instance.hide(); -} -function hideTextInstance(textInstance) { - // Noop -} -function unhideInstance(instance, props) { - if (props.visible == null || props.visible) { - instance.show(); - } -} -function unhideTextInstance(textInstance, text) { - // Noop -} -function getInstanceFromNode(node) { - throw new Error("Not implemented."); -} -function preloadInstance(type, props) { - // Return true to indicate it's already loaded - return true; -} -function waitForCommitToBeReady() { - return null; -} + if (update !== null) { + update.lane &= ~OffscreenLane; + } + } + } -var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher; -var prefix; -function describeBuiltInComponentFrame(name, source, ownerFn) { - { - if (prefix === undefined) { - // Extract the VM specific prefix used by each line. - try { - throw Error(); - } catch (x) { - var match = x.stack.trim().match(/\n( *(at )?)/); - prefix = (match && match[1]) || ""; + lanes &= ~lane; } - } // We use the prefix to ensure our stacks line up with native stack frames. - - return "\n" + prefix + name; - } -} -var reentry = false; -var componentFrameCache; - -{ - var PossiblyWeakMap$2 = typeof WeakMap === "function" ? WeakMap : Map; - componentFrameCache = new PossiblyWeakMap$2(); -} - -function describeNativeComponentFrame(fn, construct) { - // If something asked for a stack inside a fake render, it should get ignored. - if (!fn || reentry) { - return ""; - } - { - var frame = componentFrameCache.get(fn); - - if (frame !== undefined) { - return frame; + if (spawnedLane !== NoLane) { + markSpawnedDeferredLane( + root, + spawnedLane, // This render finished successfully without suspending, so we don't need + // to entangle the spawned task with the parent task. + NoLanes + ); + } } - } - - var control; - reentry = true; - var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. - - Error.prepareStackTrace = undefined; - var previousDispatcher; - { - previousDispatcher = ReactCurrentDispatcher$2.current; // Set the dispatcher in DEV because this might be call in the render function - // for warnings. + function markSpawnedDeferredLane(root, spawnedLane, entangledLanes) { + // This render spawned a deferred task. Mark it as pending. + root.pendingLanes |= spawnedLane; + root.suspendedLanes &= ~spawnedLane; // Entangle the spawned lane with the DeferredLane bit so that we know it + // was the result of another render. This lets us avoid a useDeferredValue + // waterfall — only the first level will defer. - ReactCurrentDispatcher$2.current = null; - disableLogs(); - } + var spawnedLaneIndex = laneToIndex(spawnedLane); + root.entangledLanes |= spawnedLane; + root.entanglements[spawnedLaneIndex] |= + DeferredLane | // If the parent render task suspended, we must also entangle those lanes + // with the spawned task, so that the deferred task includes all the same + // updates that the parent task did. We can exclude any lane that is not + // used for updates (e.g. Offscreen). + (entangledLanes & UpdateLanes); + } - try { - // This should throw. - if (construct) { - // Something should be setting the props in the constructor. - var Fake = function () { - throw Error(); - }; // $FlowFixMe[prop-missing] + function markRootEntangled(root, entangledLanes) { + // In addition to entangling each of the given lanes with each other, we also + // have to consider _transitive_ entanglements. For each lane that is already + // entangled with *any* of the given lanes, that lane is now transitively + // entangled with *all* the given lanes. + // + // Translated: If C is entangled with A, then entangling A with B also + // entangles C with B. + // + // If this is hard to grasp, it might help to intentionally break this + // function and look at the tests that fail in ReactTransition-test.js. Try + // commenting out one of the conditions below. + var rootEntangledLanes = (root.entangledLanes |= entangledLanes); + var entanglements = root.entanglements; + var lanes = rootEntangledLanes; - Object.defineProperty(Fake.prototype, "props", { - set: function () { - // We use a throwing setter instead of frozen or non-writable props - // because that won't throw in a non-strict mode function. - throw Error(); - } - }); + while (lanes) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; - if (typeof Reflect === "object" && Reflect.construct) { - // We construct a different control for this case to include any extra - // frames added by the construct call. - try { - Reflect.construct(Fake, []); - } catch (x) { - control = x; + if ( + // Is this one of the newly entangled lanes? + (lane & entangledLanes) | // Is this lane transitively entangled with the newly entangled lanes? + (entanglements[index] & entangledLanes) + ) { + entanglements[index] |= entangledLanes; } - Reflect.construct(fn, [], Fake); - } else { - try { - Fake.call(); - } catch (x) { - control = x; - } // $FlowFixMe[prop-missing] found when upgrading Flow - - fn.call(Fake.prototype); + lanes &= ~lane; } - } else { - try { - throw Error(); - } catch (x) { - control = x; - } // TODO(luna): This will currently only throw if the function component - // tries to access React/ReactDOM/props. We should probably make this throw - // in simple components too - - var maybePromise = fn(); // If the function component returns a promise, it's likely an async - // component, which we don't yet support. Attach a noop catch handler to - // silence the error. - // TODO: Implement component stacks for async client components? - - if (maybePromise && typeof maybePromise.catch === "function") { - maybePromise.catch(function () {}); - } - } - } catch (sample) { - // This is inlined manually because closure doesn't do it for us. - if (sample && control && typeof sample.stack === "string") { - // This extracts the first frame from the sample that isn't also in the control. - // Skipping one frame that we assume is the frame that calls the two. - var sampleLines = sample.stack.split("\n"); - var controlLines = control.stack.split("\n"); - var s = sampleLines.length - 1; - var c = controlLines.length - 1; - - while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { - // We expect at least one stack frame to be shared. - // Typically this will be the root most one. However, stack frames may be - // cut off due to maximum stack limits. In this case, one maybe cut off - // earlier than the other. We assume that the sample is longer or the same - // and there for cut off earlier. So we should find the root most frame in - // the sample somewhere in the control. - c--; - } - - for (; s >= 1 && c >= 0; s--, c--) { - // Next we find the first one that isn't the same which should be the - // frame that called our sample function and the control. - if (sampleLines[s] !== controlLines[c]) { - // In V8, the first line is describing the message but other VMs don't. - // If we're about to return the first line, and the control is also on the same - // line, that's a pretty good indicator that our sample threw at same line as - // the control. I.e. before we entered the sample frame. So we ignore this result. - // This can happen if you passed a class to function component, or non-function. - if (s !== 1 || c !== 1) { - do { - s--; - c--; // We may still have similar intermediate frames from the construct call. - // The next one that isn't the same should be our match though. - - if (c < 0 || sampleLines[s] !== controlLines[c]) { - // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. - var _frame = "\n" + sampleLines[s].replace(" at new ", " at "); // If our component frame is labeled "" - // but we have a user-provided "displayName" - // splice it in to make the stack more readable. - - if (fn.displayName && _frame.includes("")) { - _frame = _frame.replace("", fn.displayName); - } - - { - if (typeof fn === "function") { - componentFrameCache.set(fn, _frame); - } - } // Return the line we found. + } + function upgradePendingLaneToSync(root, lane) { + // Since we're upgrading the priority of the given lane, there is now pending + // sync work. + root.pendingLanes |= SyncLane; // Entangle the sync lane with the lane we're upgrading. This means SyncLane + // will not be allowed to finish without also finishing the given lane. - return _frame; - } - } while (s >= 1 && c >= 0); - } + root.entangledLanes |= SyncLane; + root.entanglements[SyncLaneIndex] |= lane; + } + function markHiddenUpdate(root, update, lane) { + var index = laneToIndex(lane); + var hiddenUpdates = root.hiddenUpdates; + var hiddenUpdatesForLane = hiddenUpdates[index]; - break; - } + if (hiddenUpdatesForLane === null) { + hiddenUpdates[index] = [update]; + } else { + hiddenUpdatesForLane.push(update); } - } - } finally { - reentry = false; - { - ReactCurrentDispatcher$2.current = previousDispatcher; - reenableLogs(); + update.lane = lane | OffscreenLane; } + function getBumpedLaneForHydration(root, renderLanes) { + var renderLane = getHighestPriorityLane(renderLanes); + var lane; - Error.prepareStackTrace = previousPrepareStackTrace; - } // Fallback to just using the name if we couldn't make it throw. + if (enableUnifiedSyncLane && (renderLane & SyncUpdateLanes) !== NoLane) { + lane = SyncHydrationLane; + } else { + switch (renderLane) { + case SyncLane: + lane = SyncHydrationLane; + break; - var name = fn ? fn.displayName || fn.name : ""; - var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ""; + case InputContinuousLane: + lane = InputContinuousHydrationLane; + break; - { - if (typeof fn === "function") { - componentFrameCache.set(fn, syntheticFrame); - } - } + case DefaultLane: + lane = DefaultHydrationLane; + break; - return syntheticFrame; -} + case TransitionLane1: + case TransitionLane2: + case TransitionLane3: + case TransitionLane4: + case TransitionLane5: + case TransitionLane6: + case TransitionLane7: + case TransitionLane8: + case TransitionLane9: + case TransitionLane10: + case TransitionLane11: + case TransitionLane12: + case TransitionLane13: + case TransitionLane14: + case TransitionLane15: + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + lane = TransitionHydrationLane; + break; -function describeClassComponentFrame(ctor, source, ownerFn) { - { - return describeNativeComponentFrame(ctor, true); - } -} -function describeFunctionComponentFrame(fn, source, ownerFn) { - { - return describeNativeComponentFrame(fn, false); - } -} + case IdleLane: + lane = IdleHydrationLane; + break; -function shouldConstruct$1(Component) { - var prototype = Component.prototype; - return !!(prototype && prototype.isReactComponent); -} + default: + // Everything else is already either a hydration lane, or shouldn't + // be retried at a hydration lane. + lane = NoLane; + break; + } + } // Check if the lane we chose is suspended. If so, that indicates that we + // already attempted and failed to hydrate at that level. Also check if we're + // already rendering that lane, which is rare but could happen. -function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { - if (type == null) { - return ""; - } + if ((lane & (root.suspendedLanes | renderLanes)) !== NoLane) { + // Give up trying to hydrate and fall back to client render. + return NoLane; + } - if (typeof type === "function") { - { - return describeNativeComponentFrame(type, shouldConstruct$1(type)); + return lane; } - } + function addFiberToLanesMap(root, fiber, lanes) { + if (!isDevToolsPresent) { + return; + } - if (typeof type === "string") { - return describeBuiltInComponentFrame(type); - } + var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; - switch (type) { - case REACT_SUSPENSE_TYPE: - return describeBuiltInComponentFrame("Suspense"); + while (lanes > 0) { + var index = laneToIndex(lanes); + var lane = 1 << index; + var updaters = pendingUpdatersLaneMap[index]; + updaters.add(fiber); + lanes &= ~lane; + } + } + function movePendingFibersToMemoized(root, lanes) { + if (!isDevToolsPresent) { + return; + } - case REACT_SUSPENSE_LIST_TYPE: - return describeBuiltInComponentFrame("SuspenseList"); - } + var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; + var memoizedUpdaters = root.memoizedUpdaters; - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_FORWARD_REF_TYPE: - return describeFunctionComponentFrame(type.render); + while (lanes > 0) { + var index = laneToIndex(lanes); + var lane = 1 << index; + var updaters = pendingUpdatersLaneMap[index]; - case REACT_MEMO_TYPE: - // Memo may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); + if (updaters.size > 0) { + updaters.forEach(function (fiber) { + var alternate = fiber.alternate; - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + if (alternate === null || !memoizedUpdaters.has(alternate)) { + memoizedUpdaters.add(fiber); + } + }); + updaters.clear(); + } - try { - // Lazy may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV( - init(payload), - source, - ownerFn - ); - } catch (x) {} + lanes &= ~lane; } } - } - - return ""; -} - -// $FlowFixMe[method-unbinding] -var hasOwnProperty = Object.prototype.hasOwnProperty; + function addTransitionToLanesMap(root, transition, lane) { + if (enableTransitionTracing) { + var transitionLanesMap = root.transitionLanes; + var index = laneToIndex(lane); + var transitions = transitionLanesMap[index]; -var loggedTypeFailures = {}; -var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; + if (transitions === null) { + transitions = new Set(); + } -function setCurrentlyValidatingElement(element) { - { - if (element) { - var owner = element._owner; - var stack = describeUnknownElementTypeFrameInDEV( - element.type, - element._source, - owner ? owner.type : null - ); - ReactDebugCurrentFrame$1.setExtraStackFrame(stack); - } else { - ReactDebugCurrentFrame$1.setExtraStackFrame(null); + transitions.add(transition); + transitionLanesMap[index] = transitions; + } } - } -} - -function checkPropTypes(typeSpecs, values, location, componentName, element) { - { - // $FlowFixMe[incompatible-use] This is okay but Flow doesn't know it. - var has = Function.call.bind(hasOwnProperty); + function getTransitionsForLanes(root, lanes) { + if (!enableTransitionTracing) { + return null; + } - for (var typeSpecName in typeSpecs) { - if (has(typeSpecs, typeSpecName)) { - var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to - // fail the render phase where it didn't fail before. So we log it. - // After these have been cleaned up, we'll let them throw. + var transitionsForLanes = []; - try { - // This is intentionally an invariant that gets caught. It's the same - // behavior as without this statement except with a better message. - if (typeof typeSpecs[typeSpecName] !== "function") { - // eslint-disable-next-line react-internal/prod-error-codes - 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`." - ); - err.name = "Invariant Violation"; - throw err; - } + while (lanes > 0) { + var index = laneToIndex(lanes); + var lane = 1 << index; + var transitions = root.transitionLanes[index]; - error$1 = typeSpecs[typeSpecName]( - values, - typeSpecName, - componentName, - location, - null, - "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" - ); - } catch (ex) { - error$1 = ex; + if (transitions !== null) { + transitions.forEach(function (transition) { + transitionsForLanes.push(transition); + }); } - if (error$1 && !(error$1 instanceof Error)) { - setCurrentlyValidatingElement(element); - - 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 - ); + lanes &= ~lane; + } - setCurrentlyValidatingElement(null); - } + if (transitionsForLanes.length === 0) { + return null; + } - if ( - error$1 instanceof Error && - !(error$1.message in loggedTypeFailures) - ) { - // Only monitor this failure once because there tends to be a lot of the - // same error. - loggedTypeFailures[error$1.message] = true; - setCurrentlyValidatingElement(element); + return transitionsForLanes; + } + function clearTransitionsForLanes(root, lanes) { + if (!enableTransitionTracing) { + return; + } - error("Failed %s type: %s", location, error$1.message); + while (lanes > 0) { + var index = laneToIndex(lanes); + var lane = 1 << index; + var transitions = root.transitionLanes[index]; - setCurrentlyValidatingElement(null); + if (transitions !== null) { + root.transitionLanes[index] = null; } + + lanes &= ~lane; } } - } -} - -var valueStack = []; -var fiberStack; - -{ - fiberStack = []; -} -var index = -1; - -function createCursor(defaultValue) { - return { - current: defaultValue - }; -} - -function pop(cursor, fiber) { - if (index < 0) { - { - error("Unexpected pop."); + var DiscreteEventPriority = SyncLane; + var ContinuousEventPriority = InputContinuousLane; + var DefaultEventPriority = DefaultLane; + var IdleEventPriority = IdleLane; + var currentUpdatePriority = NoLane; + function getCurrentUpdatePriority() { + return currentUpdatePriority; } - - return; - } - - { - if (fiber !== fiberStack[index]) { - error("Unexpected Fiber popped."); + function setCurrentUpdatePriority(newPriority) { + currentUpdatePriority = newPriority; } - } - - cursor.current = valueStack[index]; - valueStack[index] = null; + function higherEventPriority(a, b) { + return a !== 0 && a < b ? a : b; + } + function lowerEventPriority(a, b) { + return a === 0 || a > b ? a : b; + } + function isHigherEventPriority(a, b) { + return a !== 0 && a < b; + } + function lanesToEventPriority(lanes) { + var lane = getHighestPriorityLane(lanes); - { - fiberStack[index] = null; - } + if (!isHigherEventPriority(DiscreteEventPriority, lane)) { + return DiscreteEventPriority; + } - index--; -} + if (!isHigherEventPriority(ContinuousEventPriority, lane)) { + return ContinuousEventPriority; + } -function push(cursor, value, fiber) { - index++; - valueStack[index] = cursor.current; + if (includesNonIdleWork(lane)) { + return DefaultEventPriority; + } - { - fiberStack[index] = fiber; - } + return IdleEventPriority; + } - cursor.current = value; -} + // Renderers that don't support hydration + // can re-export everything from this module. + function shim$2() { + throw new Error( + "The current renderer does not support hydration. " + + "This error is likely caused by a bug in React. " + + "Please file an issue." + ); + } // Hydration (when unsupported) + var isSuspenseInstancePending = shim$2; + var isSuspenseInstanceFallback = shim$2; + var getSuspenseInstanceFallbackErrorDetails = shim$2; + var registerSuspenseInstanceRetry = shim$2; + var clearSuspenseBoundary = shim$2; + var clearSuspenseBoundaryFromContainer = shim$2; + var errorHydratingContainer = shim$2; + + // Renderers that don't support React Scopes + // can re-export everything from this module. + function shim$1() { + throw new Error( + "The current renderer does not support React Scopes. " + + "This error is likely caused by a bug in React. " + + "Please file an issue." + ); + } // React Scopes (when unsupported) -var warnedAboutMissingGetChildContext; + var prepareScopeUpdate = shim$1; + var getInstanceFromScope = shim$1; -{ - warnedAboutMissingGetChildContext = {}; -} + // Renderers that don't support hydration + // can re-export everything from this module. + function shim() { + throw new Error( + "The current renderer does not support Resources. " + + "This error is likely caused by a bug in React. " + + "Please file an issue." + ); + } // Resources (when unsupported) + var suspendResource = shim; -var emptyContextObject = {}; + var pooledTransform = new Transform(); + var NO_CONTEXT = {}; -{ - Object.freeze(emptyContextObject); -} // A cursor to the current merged context object on the stack. + { + Object.freeze(NO_CONTEXT); + } + /** Helper Methods */ -var contextStackCursor$1 = createCursor(emptyContextObject); // A cursor to a boolean indicating whether the context has changed. + function addEventListeners(instance, type, listener) { + // We need to explicitly unregister before unmount. + // For this reason we need to track subscriptions. + if (!instance._listeners) { + instance._listeners = {}; + instance._subscriptions = {}; + } -var didPerformWorkStackCursor = createCursor(false); // Keep track of the previous context object that was on the stack. -// We use this to get access to the parent context after we have already -// pushed the next context provider, and now need to merge their contexts. + instance._listeners[type] = listener; -var previousContext = emptyContextObject; + if (listener) { + if (!instance._subscriptions[type]) { + instance._subscriptions[type] = instance.subscribe( + type, + createEventHandler(instance), + instance + ); + } + } else { + if (instance._subscriptions[type]) { + instance._subscriptions[type](); -function getUnmaskedContext( - workInProgress, - Component, - didPushOwnContextIfProvider -) { - { - if (didPushOwnContextIfProvider && isContextProvider(Component)) { - // If the fiber is a context provider itself, when we read its context - // we may have already pushed its own child context on the stack. A context - // provider should not "see" its own child context. Therefore we read the - // previous (parent) context instead for a context provider. - return previousContext; + delete instance._subscriptions[type]; + } + } } - return contextStackCursor$1.current; - } -} - -function cacheContext(workInProgress, unmaskedContext, maskedContext) { - { - var instance = workInProgress.stateNode; - instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; - instance.__reactInternalMemoizedMaskedChildContext = maskedContext; - } -} + function createEventHandler(instance) { + return function handleEvent(event) { + var listener = instance._listeners[event.type]; -function getMaskedContext(workInProgress, unmaskedContext) { - { - var type = workInProgress.type; - var contextTypes = type.contextTypes; + if (!listener); + else if (typeof listener === "function") { + listener.call(instance, event); + } else if (listener.handleEvent) { + listener.handleEvent(event); + } + }; + } - if (!contextTypes) { - return emptyContextObject; - } // Avoid recreating masked context unless unmasked context has changed. - // Failing to do this will result in unnecessary calls to componentWillReceiveProps. - // This may trigger infinite loops if componentWillReceiveProps calls setState. + function destroyEventListeners(instance) { + if (instance._subscriptions) { + for (var type in instance._subscriptions) { + instance._subscriptions[type](); + } + } - var instance = workInProgress.stateNode; + instance._subscriptions = null; + instance._listeners = null; + } - if ( - instance && - instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext - ) { - return instance.__reactInternalMemoizedMaskedChildContext; + function getScaleX(props) { + if (props.scaleX != null) { + return props.scaleX; + } else if (props.scale != null) { + return props.scale; + } else { + return 1; + } } - var context = {}; + function getScaleY(props) { + if (props.scaleY != null) { + return props.scaleY; + } else if (props.scale != null) { + return props.scale; + } else { + return 1; + } + } - for (var key in contextTypes) { - context[key] = unmaskedContext[key]; + function isSameFont(oldFont, newFont) { + if (oldFont === newFont) { + return true; + } else if (typeof newFont === "string" || typeof oldFont === "string") { + return false; + } else { + return ( + newFont.fontSize === oldFont.fontSize && + newFont.fontStyle === oldFont.fontStyle && + newFont.fontVariant === oldFont.fontVariant && + newFont.fontWeight === oldFont.fontWeight && + newFont.fontFamily === oldFont.fontFamily + ); + } } + /** Render Methods */ - { - var name = getComponentNameFromFiber(workInProgress) || "Unknown"; - checkPropTypes(contextTypes, context, "context", name); - } // Cache unmasked context so we can avoid recreating masked context unless necessary. - // Context is created before the class component is instantiated so check for instance. + function applyClippingRectangleProps(instance, props) { + var prevProps = + arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + applyNodeProps(instance, props, prevProps); + instance.width = props.width; + instance.height = props.height; + } - if (instance) { - cacheContext(workInProgress, unmaskedContext, context); + function applyGroupProps(instance, props) { + var prevProps = + arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + applyNodeProps(instance, props, prevProps); + instance.width = props.width; + instance.height = props.height; } - return context; - } -} + function applyNodeProps(instance, props) { + var prevProps = + arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + var scaleX = getScaleX(props); + var scaleY = getScaleY(props); + pooledTransform + .transformTo(1, 0, 0, 1, 0, 0) + .move(props.x || 0, props.y || 0) + .rotate(props.rotation || 0, props.originX, props.originY) + .scale(scaleX, scaleY, props.originX, props.originY); -function hasContextChanged() { - { - return didPerformWorkStackCursor.current; - } -} + if (props.transform != null) { + pooledTransform.transform(props.transform); + } -function isContextProvider(type) { - { - var childContextTypes = type.childContextTypes; - return childContextTypes !== null && childContextTypes !== undefined; - } -} + if ( + instance.xx !== pooledTransform.xx || + instance.yx !== pooledTransform.yx || + instance.xy !== pooledTransform.xy || + instance.yy !== pooledTransform.yy || + instance.x !== pooledTransform.x || + instance.y !== pooledTransform.y + ) { + instance.transformTo(pooledTransform); + } -function popContext(fiber) { - { - pop(didPerformWorkStackCursor, fiber); - pop(contextStackCursor$1, fiber); - } -} + if ( + props.cursor !== prevProps.cursor || + props.title !== prevProps.title + ) { + instance.indicate(props.cursor, props.title); + } -function popTopLevelContextObject(fiber) { - { - pop(didPerformWorkStackCursor, fiber); - pop(contextStackCursor$1, fiber); - } -} + if (instance.blend && props.opacity !== prevProps.opacity) { + instance.blend(props.opacity == null ? 1 : props.opacity); + } -function pushTopLevelContextObject(fiber, context, didChange) { - { - if (contextStackCursor$1.current !== emptyContextObject) { - throw new Error( - "Unexpected context found on stack. " + - "This error is likely caused by a bug in React. Please file an issue." - ); + if (props.visible !== prevProps.visible) { + if (props.visible == null || props.visible) { + instance.show(); + } else { + instance.hide(); + } + } + + for (var type in EVENT_TYPES) { + addEventListeners(instance, EVENT_TYPES[type], props[type]); + } } - push(contextStackCursor$1, context, fiber); - push(didPerformWorkStackCursor, didChange, fiber); - } -} + function applyRenderableNodeProps(instance, props) { + var prevProps = + arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + applyNodeProps(instance, props, prevProps); -function processChildContext(fiber, type, parentContext) { - { - var instance = fiber.stateNode; - var childContextTypes = type.childContextTypes; // TODO (bvaughn) Replace this behavior with an invariant() in the future. - // It has only been added in Fiber to match the (unintentional) behavior in Stack. + if (prevProps.fill !== props.fill) { + if (props.fill && props.fill.applyFill) { + props.fill.applyFill(instance); + } else { + instance.fill(props.fill); + } + } - if (typeof instance.getChildContext !== "function") { - { - var componentName = getComponentNameFromFiber(fiber) || "Unknown"; + if ( + prevProps.stroke !== props.stroke || + prevProps.strokeWidth !== props.strokeWidth || + prevProps.strokeCap !== props.strokeCap || + prevProps.strokeJoin !== props.strokeJoin || // TODO: Consider deep check of stokeDash; may benefit VML in IE. + prevProps.strokeDash !== props.strokeDash + ) { + instance.stroke( + props.stroke, + props.strokeWidth, + props.strokeCap, + props.strokeJoin, + props.strokeDash + ); + } + } - if (!warnedAboutMissingGetChildContext[componentName]) { - warnedAboutMissingGetChildContext[componentName] = true; + function applyShapeProps(instance, props) { + var prevProps = + arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + applyRenderableNodeProps(instance, props, prevProps); + var path = props.d || childrenAsString(props.children); + var prevDelta = instance._prevDelta; + var prevPath = instance._prevPath; - 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 - ); - } + if ( + path !== prevPath || + path.delta !== prevDelta || + prevProps.height !== props.height || + prevProps.width !== props.width + ) { + instance.draw(path, props.width, props.height); + instance._prevDelta = path.delta; + instance._prevPath = path; } - - return parentContext; } - var childContext = instance.getChildContext(); + function applyTextProps(instance, props) { + var prevProps = + arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + applyRenderableNodeProps(instance, props, prevProps); + var string = props.children; - for (var contextKey in childContext) { - if (!(contextKey in childContextTypes)) { - throw new Error( - (getComponentNameFromFiber(fiber) || "Unknown") + - '.getChildContext(): key "' + - contextKey + - '" is not defined in childContextTypes.' - ); + if ( + instance._currentString !== string || + !isSameFont(props.font, prevProps.font) || + props.alignment !== prevProps.alignment || + props.path !== prevProps.path + ) { + instance.draw(string, props.font, props.alignment, props.path); + instance._currentString = string; } } + function appendInitialChild(parentInstance, child) { + if (typeof child === "string") { + // Noop for string children of Text (eg {'foo'}{'bar'}) + throw new Error("Text children should already be flattened."); + } - { - var name = getComponentNameFromFiber(fiber) || "Unknown"; - checkPropTypes(childContextTypes, childContext, "child context", name); + child.inject(parentInstance); } + function createInstance(type, props, internalInstanceHandle) { + var instance; - return assign({}, parentContext, childContext); - } -} + switch (type) { + case TYPES.CLIPPING_RECTANGLE: + instance = Mode$1.ClippingRectangle(); + instance._applyProps = applyClippingRectangleProps; + break; -function pushContextProvider(workInProgress) { - { - var instance = workInProgress.stateNode; // We push the context as early as possible to ensure stack integrity. - // If the instance does not exist yet, we will push null at first, - // and replace it on the stack later when invalidating the context. - - var memoizedMergedChildContext = - (instance && instance.__reactInternalMemoizedMergedChildContext) || - emptyContextObject; // Remember the parent context so we can merge with it later. - // Inherit the parent's did-perform-work value to avoid inadvertently blocking updates. - - previousContext = contextStackCursor$1.current; - push(contextStackCursor$1, memoizedMergedChildContext, workInProgress); - push( - didPerformWorkStackCursor, - didPerformWorkStackCursor.current, - workInProgress - ); - return true; - } -} + case TYPES.GROUP: + instance = Mode$1.Group(); + instance._applyProps = applyGroupProps; + break; -function invalidateContextProvider(workInProgress, type, didChange) { - { - var instance = workInProgress.stateNode; + case TYPES.SHAPE: + instance = Mode$1.Shape(); + instance._applyProps = applyShapeProps; + break; - if (!instance) { - 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." - ); - } + case TYPES.TEXT: + instance = Mode$1.Text( + props.children, + props.font, + props.alignment, + props.path + ); + instance._applyProps = applyTextProps; + break; + } - if (didChange) { - // Merge parent and own context. - // Skip this if we're not updating due to sCU. - // This avoids unnecessarily recomputing memoized values. - var mergedContext = processChildContext( - workInProgress, - type, - previousContext - ); - instance.__reactInternalMemoizedMergedChildContext = mergedContext; // Replace the old (or empty) context with the new one. - // It is important to unwind the context in the reverse order. + if (!instance) { + throw new Error('ReactART does not support the type "' + type + '"'); + } - pop(didPerformWorkStackCursor, workInProgress); - pop(contextStackCursor$1, workInProgress); // Now push the new context and mark that it has changed. + instance._applyProps(instance, props); - push(contextStackCursor$1, mergedContext, workInProgress); - push(didPerformWorkStackCursor, didChange, workInProgress); - } else { - pop(didPerformWorkStackCursor, workInProgress); - push(didPerformWorkStackCursor, didChange, workInProgress); + return instance; } - } -} - -function findCurrentUnmaskedContext(fiber) { - { - // Currently this is only used with renderSubtreeIntoContainer; not sure if it - // makes sense elsewhere - if (!isFiberMounted(fiber) || fiber.tag !== ClassComponent) { - 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." + function createTextInstance( + text, + rootContainerInstance, + internalInstanceHandle + ) { + return text; + } + function getPublicInstance(instance) { + return instance; + } + function prepareForCommit() { + // Noop + return null; + } + function resetTextContent(domElement) { + // Noop + } + function getRootHostContext() { + return NO_CONTEXT; + } + function getChildHostContext() { + return NO_CONTEXT; + } + var scheduleTimeout = setTimeout; + var cancelTimeout = clearTimeout; + var noTimeout = -1; + function shouldSetTextContent(type, props) { + return ( + typeof props.children === "string" || typeof props.children === "number" ); } + function getCurrentEventPriority() { + return DefaultEventPriority; + } + function shouldAttemptEagerTransition() { + return false; + } // The ART renderer is secondary to the React DOM renderer. - var node = fiber; - - do { - switch (node.tag) { - case HostRoot: - return node.stateNode.context; - - case ClassComponent: { - var Component = node.type; - - if (isContextProvider(Component)) { - return node.stateNode.__reactInternalMemoizedMergedChildContext; - } - - break; - } - } // $FlowFixMe[incompatible-type] we bail out when we get a null - - node = node.return; - } while (node !== null); - - throw new Error( - "Found unexpected detached subtree parent. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } -} - -// We use the existence of the state object as an indicator that the component -// is hidden. -var OffscreenVisible = - /* */ - 1; -var OffscreenDetached = - /* */ - 2; -var OffscreenPassiveEffectsConnected = - /* */ - 4; -function isOffscreenManual(offscreenFiber) { - return ( - offscreenFiber.memoizedProps !== null && - offscreenFiber.memoizedProps.mode === "manual" - ); -} - -/** - * inlined Object.is polyfill to avoid requiring consumers ship their own - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is - */ -function is(x, y) { - return ( - (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare - ); -} - -var objectIs = typeof Object.is === "function" ? Object.is : is; // $FlowFixMe[method-unbinding] - -var nativeConsole = console; -var nativeConsoleLog = null; -var pendingGroupArgs = []; -var printedGroupIndex = -1; - -function formatLanes(laneOrLanes) { - return "0b" + laneOrLanes.toString(2).padStart(31, "0"); -} - -function group() { - for ( - var _len = arguments.length, groupArgs = new Array(_len), _key = 0; - _key < _len; - _key++ - ) { - groupArgs[_key] = arguments[_key]; - } - - pendingGroupArgs.push(groupArgs); - - if (nativeConsoleLog === null) { - nativeConsoleLog = nativeConsole.log; - nativeConsole.log = log; - } -} - -function groupEnd() { - pendingGroupArgs.pop(); - - while (printedGroupIndex >= pendingGroupArgs.length) { - nativeConsole.groupEnd(); - printedGroupIndex--; - } - - if (pendingGroupArgs.length === 0) { - nativeConsole.log = nativeConsoleLog; - nativeConsoleLog = null; - } -} + var warnsIfNotActing = false; + function appendChild(parentInstance, child) { + if (child.parentNode === parentInstance) { + child.eject(); + } -function log() { - if (printedGroupIndex < pendingGroupArgs.length - 1) { - for (var i = printedGroupIndex + 1; i < pendingGroupArgs.length; i++) { - var groupArgs = pendingGroupArgs[i]; - nativeConsole.group.apply(nativeConsole, groupArgs); + child.inject(parentInstance); } + function appendChildToContainer(parentInstance, child) { + if (child.parentNode === parentInstance) { + child.eject(); + } - printedGroupIndex = pendingGroupArgs.length - 1; - } + child.inject(parentInstance); + } + function insertBefore(parentInstance, child, beforeChild) { + if (child === beforeChild) { + throw new Error("ReactART: Can not insert node before itself"); + } - if (typeof nativeConsoleLog === "function") { - nativeConsoleLog.apply(void 0, arguments); - } else { - nativeConsole.log.apply(nativeConsole, arguments); - } -} + child.injectBefore(beforeChild); + } + function insertInContainerBefore(parentInstance, child, beforeChild) { + if (child === beforeChild) { + throw new Error("ReactART: Can not insert node before itself"); + } -var REACT_LOGO_STYLE = - "background-color: #20232a; color: #61dafb; padding: 0 2px;"; -function logCommitStarted(lanes) { - { - if (enableDebugTracing) { - group( - "%c\u269B\uFE0F%c commit%c (" + formatLanes(lanes) + ")", - REACT_LOGO_STYLE, - "", - "font-weight: normal;" - ); + child.injectBefore(beforeChild); } - } -} -function logCommitStopped() { - { - if (enableDebugTracing) { - groupEnd(); + function removeChild(parentInstance, child) { + destroyEventListeners(child); + child.eject(); } - } -} -var PossiblyWeakMap$1 = typeof WeakMap === "function" ? WeakMap : Map; // $FlowFixMe[incompatible-type]: Flow cannot handle polymorphic WeakMaps - -var wakeableIDs = new PossiblyWeakMap$1(); -var wakeableID = 0; - -function getWakeableID(wakeable) { - if (!wakeableIDs.has(wakeable)) { - wakeableIDs.set(wakeable, wakeableID++); - } - - return wakeableIDs.get(wakeable); -} - -function logComponentSuspended(componentName, wakeable) { - { - if (enableDebugTracing) { - var id = getWakeableID(wakeable); - var display = wakeable.displayName || wakeable; - log( - "%c\u269B\uFE0F%c " + componentName + " suspended", - REACT_LOGO_STYLE, - "color: #80366d; font-weight: bold;", - id, - display - ); - wakeable.then( - function () { - log( - "%c\u269B\uFE0F%c " + componentName + " resolved", - REACT_LOGO_STYLE, - "color: #80366d; font-weight: bold;", - id, - display - ); - }, - function () { - log( - "%c\u269B\uFE0F%c " + componentName + " rejected", - REACT_LOGO_STYLE, - "color: #80366d; font-weight: bold;", - id, - display - ); - } - ); + function removeChildFromContainer(parentInstance, child) { + destroyEventListeners(child); + child.eject(); } - } -} -function logLayoutEffectsStarted(lanes) { - { - if (enableDebugTracing) { - group( - "%c\u269B\uFE0F%c layout effects%c (" + formatLanes(lanes) + ")", - REACT_LOGO_STYLE, - "", - "font-weight: normal;" - ); + function commitTextUpdate(textInstance, oldText, newText) { + // Noop } - } -} -function logLayoutEffectsStopped() { - { - if (enableDebugTracing) { - groupEnd(); + function commitMount(instance, type, newProps) { + // Noop } - } -} -function logPassiveEffectsStarted(lanes) { - { - if (enableDebugTracing) { - group( - "%c\u269B\uFE0F%c passive effects%c (" + formatLanes(lanes) + ")", - REACT_LOGO_STYLE, - "", - "font-weight: normal;" - ); + function commitUpdate(instance, updatePayload, type, oldProps, newProps) { + instance._applyProps(instance, newProps, oldProps); } - } -} -function logPassiveEffectsStopped() { - { - if (enableDebugTracing) { - groupEnd(); + function hideInstance(instance) { + instance.hide(); } - } -} -function logRenderStarted(lanes) { - { - if (enableDebugTracing) { - group( - "%c\u269B\uFE0F%c render%c (" + formatLanes(lanes) + ")", - REACT_LOGO_STYLE, - "", - "font-weight: normal;" - ); + function hideTextInstance(textInstance) { + // Noop } - } -} -function logRenderStopped() { - { - if (enableDebugTracing) { - groupEnd(); + function unhideInstance(instance, props) { + if (props.visible == null || props.visible) { + instance.show(); + } } - } -} -function logForceUpdateScheduled(componentName, lane) { - { - if (enableDebugTracing) { - log( - "%c\u269B\uFE0F%c " + - componentName + - " forced update %c(" + - formatLanes(lane) + - ")", - REACT_LOGO_STYLE, - "color: #db2e1f; font-weight: bold;", - "" - ); + function unhideTextInstance(textInstance, text) { + // Noop } - } -} -function logStateUpdateScheduled(componentName, lane, payloadOrAction) { - { - if (enableDebugTracing) { - log( - "%c\u269B\uFE0F%c " + - componentName + - " updated state %c(" + - formatLanes(lane) + - ")", - REACT_LOGO_STYLE, - "color: #01a252; font-weight: bold;", - "", - payloadOrAction - ); + function getInstanceFromNode(node) { + throw new Error("Not implemented."); + } + function preloadInstance(type, props) { + // Return true to indicate it's already loaded + return true; + } + function waitForCommitToBeReady() { + return null; } - } -} - -// This is imported by the event replaying implementation in React DOM. It's -// in a separate file to break a circular dependency between the renderer and -// the reconciler. -function isRootDehydrated(root) { - var currentState = root.current.memoizedState; - return currentState.isDehydrated; -} -var contextStackCursor = createCursor(null); -var contextFiberStackCursor = createCursor(null); -var rootInstanceStackCursor = createCursor(null); // Represents the nearest host transition provider (in React DOM, a
) + var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher; + var prefix; + function describeBuiltInComponentFrame(name, source, ownerFn) { + { + if (prefix === undefined) { + // Extract the VM specific prefix used by each line. + try { + throw Error(); + } catch (x) { + var match = x.stack.trim().match(/\n( *(at )?)/); + prefix = (match && match[1]) || ""; + } + } // We use the prefix to ensure our stacks line up with native stack frames. -function requiredContext(c) { - { - if (c === null) { - error( - "Expected host context to exist. This error is likely caused by a bug " + - "in React. Please file an issue." - ); + return "\n" + prefix + name; + } } - } + var reentry = false; + var componentFrameCache; - return c; -} - -function getRootHostContainer() { - var rootInstance = requiredContext(rootInstanceStackCursor.current); - return rootInstance; -} + { + var PossiblyWeakMap$2 = typeof WeakMap === "function" ? WeakMap : Map; + componentFrameCache = new PossiblyWeakMap$2(); + } -function pushHostContainer(fiber, nextRootInstance) { - // Push current root instance onto the stack; - // This allows us to reset root when portals are popped. - push(rootInstanceStackCursor, nextRootInstance, fiber); // Track the context and the Fiber that provided it. - // This enables us to pop only Fibers that provide unique contexts. + function describeNativeComponentFrame(fn, construct) { + // If something asked for a stack inside a fake render, it should get ignored. + if (!fn || reentry) { + return ""; + } - push(contextFiberStackCursor, fiber, fiber); // Finally, we need to push the host context to the stack. - // However, we can't just call getRootHostContext() and push it because - // we'd have a different number of entries on the stack depending on - // whether getRootHostContext() throws somewhere in renderer code or not. - // So we push an empty value first. This lets us safely unwind on errors. + { + var frame = componentFrameCache.get(fn); - push(contextStackCursor, null, fiber); - var nextRootContext = getRootHostContext(); // Now that we know this function doesn't throw, replace it. + if (frame !== undefined) { + return frame; + } + } - pop(contextStackCursor, fiber); - push(contextStackCursor, nextRootContext, fiber); -} + var control; + reentry = true; + var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. -function popHostContainer(fiber) { - pop(contextStackCursor, fiber); - pop(contextFiberStackCursor, fiber); - pop(rootInstanceStackCursor, fiber); -} + Error.prepareStackTrace = undefined; + var previousDispatcher; -function getHostContext() { - var context = requiredContext(contextStackCursor.current); - return context; -} + { + previousDispatcher = ReactCurrentDispatcher$2.current; // Set the dispatcher in DEV because this might be call in the render function + // for warnings. -function pushHostContext(fiber) { - var context = requiredContext(contextStackCursor.current); - var nextContext = getChildHostContext(); // Don't push this Fiber's context unless it's unique. + ReactCurrentDispatcher$2.current = null; + disableLogs(); + } - if (context !== nextContext) { - // Track the context and the Fiber that provided it. - // This enables us to pop only Fibers that provide unique contexts. - push(contextFiberStackCursor, fiber, fiber); - push(contextStackCursor, nextContext, fiber); - } -} + try { + // This should throw. + if (construct) { + // Something should be setting the props in the constructor. + var Fake = function () { + throw Error(); + }; // $FlowFixMe[prop-missing] + + Object.defineProperty(Fake.prototype, "props", { + set: function () { + // We use a throwing setter instead of frozen or non-writable props + // because that won't throw in a non-strict mode function. + throw Error(); + } + }); -function popHostContext(fiber) { - if (contextFiberStackCursor.current === fiber) { - // Do not pop unless this Fiber provided the current context. - // pushHostContext() only pushes Fibers that provide unique contexts. - pop(contextStackCursor, fiber); - pop(contextFiberStackCursor, fiber); - } -} + if (typeof Reflect === "object" && Reflect.construct) { + // We construct a different control for this case to include any extra + // frames added by the construct call. + try { + Reflect.construct(Fake, []); + } catch (x) { + control = x; + } -var isHydrating = false; // This flag allows for warning supression when we expect there to be mismatches -// due to earlier mismatches or a suspended fiber. + Reflect.construct(fn, [], Fake); + } else { + try { + Fake.call(); + } catch (x) { + control = x; + } // $FlowFixMe[prop-missing] found when upgrading Flow -var didSuspendOrErrorDEV = false; // Hydration errors that were thrown inside this boundary + fn.call(Fake.prototype); + } + } else { + try { + throw Error(); + } catch (x) { + control = x; + } // TODO(luna): This will currently only throw if the function component + // tries to access React/ReactDOM/props. We should probably make this throw + // in simple components too + + var maybePromise = fn(); // If the function component returns a promise, it's likely an async + // component, which we don't yet support. Attach a noop catch handler to + // silence the error. + // TODO: Implement component stacks for async client components? + + if (maybePromise && typeof maybePromise.catch === "function") { + maybePromise.catch(function () {}); + } + } + } catch (sample) { + // This is inlined manually because closure doesn't do it for us. + if (sample && control && typeof sample.stack === "string") { + // This extracts the first frame from the sample that isn't also in the control. + // Skipping one frame that we assume is the frame that calls the two. + var sampleLines = sample.stack.split("\n"); + var controlLines = control.stack.split("\n"); + var s = sampleLines.length - 1; + var c = controlLines.length - 1; + + while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { + // We expect at least one stack frame to be shared. + // Typically this will be the root most one. However, stack frames may be + // cut off due to maximum stack limits. In this case, one maybe cut off + // earlier than the other. We assume that the sample is longer or the same + // and there for cut off earlier. So we should find the root most frame in + // the sample somewhere in the control. + c--; + } -var hydrationErrors = null; -function didSuspendOrErrorWhileHydratingDEV() { - { - return didSuspendOrErrorDEV; - } -} + for (; s >= 1 && c >= 0; s--, c--) { + // Next we find the first one that isn't the same which should be the + // frame that called our sample function and the control. + if (sampleLines[s] !== controlLines[c]) { + // In V8, the first line is describing the message but other VMs don't. + // If we're about to return the first line, and the control is also on the same + // line, that's a pretty good indicator that our sample threw at same line as + // the control. I.e. before we entered the sample frame. So we ignore this result. + // This can happen if you passed a class to function component, or non-function. + if (s !== 1 || c !== 1) { + do { + s--; + c--; // We may still have similar intermediate frames from the construct call. + // The next one that isn't the same should be our match though. + + if (c < 0 || sampleLines[s] !== controlLines[c]) { + // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. + var _frame = + "\n" + sampleLines[s].replace(" at new ", " at "); // If our component frame is labeled "" + // but we have a user-provided "displayName" + // splice it in to make the stack more readable. + + if (fn.displayName && _frame.includes("")) { + _frame = _frame.replace("", fn.displayName); + } -function prepareToHydrateHostInstance(fiber, hostContext) { - { - throw new Error( - "Expected prepareToHydrateHostInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } -} + { + if (typeof fn === "function") { + componentFrameCache.set(fn, _frame); + } + } // Return the line we found. -function prepareToHydrateHostTextInstance(fiber) { - { - throw new Error( - "Expected prepareToHydrateHostTextInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } -} + return _frame; + } + } while (s >= 1 && c >= 0); + } -function prepareToHydrateHostSuspenseInstance(fiber) { - { - throw new Error( - "Expected prepareToHydrateHostSuspenseInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } -} + break; + } + } + } + } finally { + reentry = false; -function popHydrationState(fiber) { - { - return false; - } -} + { + ReactCurrentDispatcher$2.current = previousDispatcher; + reenableLogs(); + } -function upgradeHydrationErrorsToRecoverable() { - if (hydrationErrors !== null) { - // Successfully completed a forced client render. The errors that occurred - // during the hydration attempt are now recovered. We will log them in - // commit phase, once the entire tree has finished. - queueRecoverableErrors(hydrationErrors); - hydrationErrors = null; - } -} + Error.prepareStackTrace = previousPrepareStackTrace; + } // Fallback to just using the name if we couldn't make it throw. -function getIsHydrating() { - return isHydrating; -} + var name = fn ? fn.displayName || fn.name : ""; + var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ""; -function queueHydrationError(error) { - if (hydrationErrors === null) { - hydrationErrors = [error]; - } else { - hydrationErrors.push(error); - } -} + { + if (typeof fn === "function") { + componentFrameCache.set(fn, syntheticFrame); + } + } -// we wait until the current render is over (either finished or interrupted) -// before adding it to the fiber/hook queue. Push to this array so we can -// access the queue, fiber, update, et al later. - -var concurrentQueues = []; -var concurrentQueuesIndex = 0; -var concurrentlyUpdatedLanes = NoLanes; -function finishQueueingConcurrentUpdates() { - var endIndex = concurrentQueuesIndex; - concurrentQueuesIndex = 0; - concurrentlyUpdatedLanes = NoLanes; - var i = 0; - - while (i < endIndex) { - var fiber = concurrentQueues[i]; - concurrentQueues[i++] = null; - var queue = concurrentQueues[i]; - concurrentQueues[i++] = null; - var update = concurrentQueues[i]; - concurrentQueues[i++] = null; - var lane = concurrentQueues[i]; - concurrentQueues[i++] = null; - - if (queue !== null && update !== null) { - var pending = queue.pending; + return syntheticFrame; + } - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; + function describeClassComponentFrame(ctor, source, ownerFn) { + { + return describeNativeComponentFrame(ctor, true); + } + } + function describeFunctionComponentFrame(fn, source, ownerFn) { + { + return describeNativeComponentFrame(fn, false); } - - queue.pending = update; } - if (lane !== NoLane) { - markUpdateLaneFromFiberToRoot(fiber, update, lane); + function shouldConstruct$1(Component) { + var prototype = Component.prototype; + return !!(prototype && prototype.isReactComponent); } - } -} -function getConcurrentlyUpdatedLanes() { - return concurrentlyUpdatedLanes; -} -function enqueueUpdate$1(fiber, queue, update, lane) { - // Don't update the `childLanes` on the return path yet. If we already in - // the middle of rendering, wait until after it has completed. - concurrentQueues[concurrentQueuesIndex++] = fiber; - concurrentQueues[concurrentQueuesIndex++] = queue; - concurrentQueues[concurrentQueuesIndex++] = update; - concurrentQueues[concurrentQueuesIndex++] = lane; - concurrentlyUpdatedLanes = mergeLanes(concurrentlyUpdatedLanes, lane); // The fiber's `lane` field is used in some places to check if any work is - // scheduled, to perform an eager bailout, so we need to update it immediately. - // TODO: We should probably move this to the "shared" queue instead. - - fiber.lanes = mergeLanes(fiber.lanes, lane); - var alternate = fiber.alternate; - - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, lane); - } -} + function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { + if (type == null) { + return ""; + } -function enqueueConcurrentHookUpdate(fiber, queue, update, lane) { - var concurrentQueue = queue; - var concurrentUpdate = update; - enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); - return getRootForUpdatedFiber(fiber); -} -function enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update) { - // This function is used to queue an update that doesn't need a rerender. The - // only reason we queue it is in case there's a subsequent higher priority - // update that causes it to be rebased. - var lane = NoLane; - var concurrentQueue = queue; - var concurrentUpdate = update; - enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); // Usually we can rely on the upcoming render phase to process the concurrent - // queue. However, since this is a bail out, we're not scheduling any work - // here. So the update we just queued will leak until something else happens - // to schedule work (if ever). - // - // Check if we're currently in the middle of rendering a tree, and if not, - // process the queue immediately to prevent a leak. - - var isConcurrentlyRendering = getWorkInProgressRoot() !== null; - - if (!isConcurrentlyRendering) { - finishQueueingConcurrentUpdates(); - } -} -function enqueueConcurrentClassUpdate(fiber, queue, update, lane) { - var concurrentQueue = queue; - var concurrentUpdate = update; - enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); - return getRootForUpdatedFiber(fiber); -} -function enqueueConcurrentRenderForLane(fiber, lane) { - enqueueUpdate$1(fiber, null, null, lane); - return getRootForUpdatedFiber(fiber); -} // Calling this function outside this module should only be done for backwards -// compatibility and should always be accompanied by a warning. - -function unsafe_markUpdateLaneFromFiberToRoot(sourceFiber, lane) { - // NOTE: For Hyrum's Law reasons, if an infinite update loop is detected, it - // should throw before `markUpdateLaneFromFiberToRoot` is called. But this is - // undefined behavior and we can change it if we need to; it just so happens - // that, at the time of this writing, there's an internal product test that - // happens to rely on this. - var root = getRootForUpdatedFiber(sourceFiber); - markUpdateLaneFromFiberToRoot(sourceFiber, null, lane); - return root; -} + if (typeof type === "function") { + { + return describeNativeComponentFrame(type, shouldConstruct$1(type)); + } + } -function markUpdateLaneFromFiberToRoot(sourceFiber, update, lane) { - // Update the source fiber's lanes - sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane); - var alternate = sourceFiber.alternate; + if (typeof type === "string") { + return describeBuiltInComponentFrame(type); + } - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, lane); - } // Walk the parent path to the root and update the child lanes. + switch (type) { + case REACT_SUSPENSE_TYPE: + return describeBuiltInComponentFrame("Suspense"); - var isHidden = false; - var parent = sourceFiber.return; - var node = sourceFiber; + case REACT_SUSPENSE_LIST_TYPE: + return describeBuiltInComponentFrame("SuspenseList"); + } - while (parent !== null) { - parent.childLanes = mergeLanes(parent.childLanes, lane); - alternate = parent.alternate; + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_FORWARD_REF_TYPE: + return describeFunctionComponentFrame(type.render); - if (alternate !== null) { - alternate.childLanes = mergeLanes(alternate.childLanes, lane); - } + case REACT_MEMO_TYPE: + // Memo may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + type.type, + source, + ownerFn + ); - if (parent.tag === OffscreenComponent) { - // Check if this offscreen boundary is currently hidden. - // - // The instance may be null if the Offscreen parent was unmounted. Usually - // the parent wouldn't be reachable in that case because we disconnect - // fibers from the tree when they are deleted. However, there's a weird - // edge case where setState is called on a fiber that was interrupted - // before it ever mounted. Because it never mounts, it also never gets - // deleted. Because it never gets deleted, its return pointer never gets - // disconnected. Which means it may be attached to a deleted Offscreen - // parent node. (This discovery suggests it may be better for memory usage - // if we don't attach the `return` pointer until the commit phase, though - // in order to do that we'd need some other way to track the return - // pointer during the initial render, like on the stack.) - // - // This case is always accompanied by a warning, but we still need to - // account for it. (There may be other cases that we haven't discovered, - // too.) - var offscreenInstance = parent.stateNode; + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - if ( - offscreenInstance !== null && - !(offscreenInstance._visibility & OffscreenVisible) - ) { - isHidden = true; + try { + // Lazy may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + init(payload), + source, + ownerFn + ); + } catch (x) {} + } + } } - } - node = parent; - parent = parent.return; - } + return ""; + } - if (isHidden && update !== null && node.tag === HostRoot) { - var root = node.stateNode; - markHiddenUpdate(root, update, lane); - } -} + // $FlowFixMe[method-unbinding] + var hasOwnProperty = Object.prototype.hasOwnProperty; -function getRootForUpdatedFiber(sourceFiber) { - // TODO: We will detect and infinite update loop and throw even if this fiber - // has already unmounted. This isn't really necessary but it happens to be the - // current behavior we've used for several release cycles. Consider not - // performing this check if the updated fiber already unmounted, since it's - // not possible for that to cause an infinite update loop. - throwIfInfiniteUpdateLoopDetected(); // When a setState happens, we must ensure the root is scheduled. Because - // update queues do not have a backpointer to the root, the only way to do - // this currently is to walk up the return path. This used to not be a big - // deal because we would have to walk up the return path to set - // the `childLanes`, anyway, but now those two traversals happen at - // different times. - // TODO: Consider adding a `root` backpointer on the update queue. - - detectUpdateOnUnmountedFiber(sourceFiber, sourceFiber); - var node = sourceFiber; - var parent = node.return; - - while (parent !== null) { - detectUpdateOnUnmountedFiber(sourceFiber, node); - node = parent; - parent = node.return; - } - - return node.tag === HostRoot ? node.stateNode : null; -} + var loggedTypeFailures = {}; + var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; -function detectUpdateOnUnmountedFiber(sourceFiber, parent) { - { - var alternate = parent.alternate; + function setCurrentlyValidatingElement(element) { + { + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV( + element.type, + element._source, + owner ? owner.type : null + ); + ReactDebugCurrentFrame$1.setExtraStackFrame(stack); + } else { + ReactDebugCurrentFrame$1.setExtraStackFrame(null); + } + } + } - if ( - alternate === null && - (parent.flags & (Placement | Hydrating)) !== NoFlags$1 + function checkPropTypes( + typeSpecs, + values, + location, + componentName, + element ) { - warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); - } - } -} + { + // $FlowFixMe[incompatible-use] This is okay but Flow doesn't know it. + var has = Function.call.bind(hasOwnProperty); -var UpdateState = 0; -var ReplaceState = 1; -var ForceUpdate = 2; -var CaptureUpdate = 3; // Global state that is reset at the beginning of calling `processUpdateQueue`. -// It should only be read right after calling `processUpdateQueue`, via -// `checkHasForceUpdateAfterProcessing`. + for (var typeSpecName in typeSpecs) { + if (has(typeSpecs, typeSpecName)) { + var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to + // fail the render phase where it didn't fail before. So we log it. + // After these have been cleaned up, we'll let them throw. -var hasForceUpdate = false; -var didWarnUpdateInsideUpdate; -var currentlyProcessingQueue; + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + if (typeof typeSpecs[typeSpecName] !== "function") { + // eslint-disable-next-line react-internal/prod-error-codes + 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`." + ); + err.name = "Invariant Violation"; + throw err; + } -{ - didWarnUpdateInsideUpdate = false; - currentlyProcessingQueue = null; -} + error$1 = typeSpecs[typeSpecName]( + values, + typeSpecName, + componentName, + location, + null, + "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" + ); + } catch (ex) { + error$1 = ex; + } -function initializeUpdateQueue(fiber) { - var queue = { - baseState: fiber.memoizedState, - firstBaseUpdate: null, - lastBaseUpdate: null, - shared: { - pending: null, - lanes: NoLanes, - hiddenCallbacks: null - }, - callbacks: null - }; - fiber.updateQueue = queue; -} -function cloneUpdateQueue(current, workInProgress) { - // Clone the update queue from current. Unless it's already a clone. - var queue = workInProgress.updateQueue; - var currentQueue = current.updateQueue; - - if (queue === currentQueue) { - var clone = { - baseState: currentQueue.baseState, - firstBaseUpdate: currentQueue.firstBaseUpdate, - lastBaseUpdate: currentQueue.lastBaseUpdate, - shared: currentQueue.shared, - callbacks: null - }; - workInProgress.updateQueue = clone; - } -} -function createUpdate(lane) { - var update = { - lane: lane, - tag: UpdateState, - payload: null, - callback: null, - next: null - }; - return update; -} -function enqueueUpdate(fiber, update, lane) { - var updateQueue = fiber.updateQueue; + if (error$1 && !(error$1 instanceof Error)) { + setCurrentlyValidatingElement(element); - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return null; - } + 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 + ); - var sharedQueue = updateQueue.shared; + setCurrentlyValidatingElement(null); + } - { - if ( - currentlyProcessingQueue === sharedQueue && - !didWarnUpdateInsideUpdate - ) { - var componentName = getComponentNameFromFiber(fiber); - - 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.\n\nPlease update the following component: %s", - componentName - ); + if ( + error$1 instanceof Error && + !(error$1.message in loggedTypeFailures) + ) { + // Only monitor this failure once because there tends to be a lot of the + // same error. + loggedTypeFailures[error$1.message] = true; + setCurrentlyValidatingElement(element); - didWarnUpdateInsideUpdate = true; + error("Failed %s type: %s", location, error$1.message); + + setCurrentlyValidatingElement(null); + } + } + } + } } - } - if (isUnsafeClassRenderPhaseUpdate()) { - // This is an unsafe render phase update. Add directly to the update - // queue so we can process it immediately during the current render. - var pending = sharedQueue.pending; + var valueStack = []; + var fiberStack; - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; + { + fiberStack = []; } - sharedQueue.pending = update; // Update the childLanes even though we're most likely already rendering - // this fiber. This is for backwards compatibility in the case where you - // update a different component during render phase than the one that is - // currently renderings (a pattern that is accompanied by a warning). + var index = -1; - return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); - } else { - return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); - } -} -function entangleTransitions(root, fiber, lane) { - var updateQueue = fiber.updateQueue; + function createCursor(defaultValue) { + return { + current: defaultValue + }; + } - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return; - } + function pop(cursor, fiber) { + if (index < 0) { + { + error("Unexpected pop."); + } - var sharedQueue = updateQueue.shared; + return; + } - if (isTransitionLane(lane)) { - var queueLanes = sharedQueue.lanes; // If any entangled lanes are no longer pending on the root, then they must - // have finished. We can remove them from the shared queue, which represents - // a superset of the actually pending lanes. In some cases we may entangle - // more than we need to, but that's OK. In fact it's worse if we *don't* - // entangle when we should. - - queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. - - var newQueueLanes = mergeLanes(queueLanes, lane); - sharedQueue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if - // the lane finished since the last time we entangled it. So we need to - // entangle it again, just to be sure. - - markRootEntangled(root, newQueueLanes); - } -} -function enqueueCapturedUpdate(workInProgress, capturedUpdate) { - // Captured updates are updates that are thrown by a child during the render - // phase. They should be discarded if the render is aborted. Therefore, - // we should only put them on the work-in-progress queue, not the current one. - var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone. - - var current = workInProgress.alternate; - - if (current !== null) { - var currentQueue = current.updateQueue; - - if (queue === currentQueue) { - // The work-in-progress queue is the same as current. This happens when - // we bail out on a parent fiber that then captures an error thrown by - // a child. Since we want to append the update only to the work-in - // -progress queue, we need to clone the updates. We usually clone during - // processUpdateQueue, but that didn't happen in this case because we - // skipped over the parent when we bailed out. - var newFirst = null; - var newLast = null; - var firstBaseUpdate = queue.firstBaseUpdate; + { + if (fiber !== fiberStack[index]) { + error("Unexpected Fiber popped."); + } + } - if (firstBaseUpdate !== null) { - // Loop through the updates and clone them. - var update = firstBaseUpdate; + cursor.current = valueStack[index]; + valueStack[index] = null; - do { - var clone = { - lane: update.lane, - tag: update.tag, - payload: update.payload, - // When this update is rebased, we should not fire its - // callback again. - callback: null, - next: null - }; + { + fiberStack[index] = null; + } - if (newLast === null) { - newFirst = newLast = clone; - } else { - newLast.next = clone; - newLast = clone; - } // $FlowFixMe[incompatible-type] we bail out when we get a null + index--; + } - update = update.next; - } while (update !== null); // Append the captured update the end of the cloned list. + function push(cursor, value, fiber) { + index++; + valueStack[index] = cursor.current; - if (newLast === null) { - newFirst = newLast = capturedUpdate; - } else { - newLast.next = capturedUpdate; - newLast = capturedUpdate; - } - } else { - // There are no base updates. - newFirst = newLast = capturedUpdate; + { + fiberStack[index] = fiber; } - queue = { - baseState: currentQueue.baseState, - firstBaseUpdate: newFirst, - lastBaseUpdate: newLast, - shared: currentQueue.shared, - callbacks: currentQueue.callbacks - }; - workInProgress.updateQueue = queue; - return; + cursor.current = value; } - } // Append the update to the end of the list. - var lastBaseUpdate = queue.lastBaseUpdate; + var warnedAboutMissingGetChildContext; - if (lastBaseUpdate === null) { - queue.firstBaseUpdate = capturedUpdate; - } else { - lastBaseUpdate.next = capturedUpdate; - } + { + warnedAboutMissingGetChildContext = {}; + } - queue.lastBaseUpdate = capturedUpdate; -} + var emptyContextObject = {}; -function getStateFromUpdate( - workInProgress, - queue, - update, - prevState, - nextProps, - instance -) { - switch (update.tag) { - case ReplaceState: { - var payload = update.payload; - - if (typeof payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); - } + { + Object.freeze(emptyContextObject); + } // A cursor to the current merged context object on the stack. - var nextState = payload.call(instance, prevState, nextProps); + var contextStackCursor$1 = createCursor(emptyContextObject); // A cursor to a boolean indicating whether the context has changed. - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + var didPerformWorkStackCursor = createCursor(false); // Keep track of the previous context object that was on the stack. + // We use this to get access to the parent context after we have already + // pushed the next context provider, and now need to merge their contexts. - try { - payload.call(instance, prevState, nextProps); - } finally { - setIsStrictModeForDevtools(false); - } - } + var previousContext = emptyContextObject; - exitDisallowedContextReadInDEV(); + function getUnmaskedContext( + workInProgress, + Component, + didPushOwnContextIfProvider + ) { + { + if (didPushOwnContextIfProvider && isContextProvider(Component)) { + // If the fiber is a context provider itself, when we read its context + // we may have already pushed its own child context on the stack. A context + // provider should not "see" its own child context. Therefore we read the + // previous (parent) context instead for a context provider. + return previousContext; } - return nextState; - } // State object - - return payload; + return contextStackCursor$1.current; + } } - case CaptureUpdate: { - workInProgress.flags = - (workInProgress.flags & ~ShouldCapture) | DidCapture; + function cacheContext(workInProgress, unmaskedContext, maskedContext) { + { + var instance = workInProgress.stateNode; + instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; + instance.__reactInternalMemoizedMaskedChildContext = maskedContext; + } } - // Intentional fallthrough - case UpdateState: { - var _payload = update.payload; - var partialState; + function getMaskedContext(workInProgress, unmaskedContext) { + { + var type = workInProgress.type; + var contextTypes = type.contextTypes; - if (typeof _payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); - } + if (!contextTypes) { + return emptyContextObject; + } // Avoid recreating masked context unless unmasked context has changed. + // Failing to do this will result in unnecessary calls to componentWillReceiveProps. + // This may trigger infinite loops if componentWillReceiveProps calls setState. - partialState = _payload.call(instance, prevState, nextProps); + var instance = workInProgress.stateNode; - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + if ( + instance && + instance.__reactInternalMemoizedUnmaskedChildContext === + unmaskedContext + ) { + return instance.__reactInternalMemoizedMaskedChildContext; + } - try { - _payload.call(instance, prevState, nextProps); - } finally { - setIsStrictModeForDevtools(false); - } - } + var context = {}; - exitDisallowedContextReadInDEV(); + for (var key in contextTypes) { + context[key] = unmaskedContext[key]; } - } else { - // Partial state object - partialState = _payload; - } - if (partialState === null || partialState === undefined) { - // Null and undefined are treated as no-ops. - return prevState; - } // Merge the partial state and the previous state. + { + var name = getComponentNameFromFiber(workInProgress) || "Unknown"; + checkPropTypes(contextTypes, context, "context", name); + } // Cache unmasked context so we can avoid recreating masked context unless necessary. + // Context is created before the class component is instantiated so check for instance. - return assign({}, prevState, partialState); - } + if (instance) { + cacheContext(workInProgress, unmaskedContext, context); + } - case ForceUpdate: { - hasForceUpdate = true; - return prevState; + return context; + } } - } - - return prevState; -} - -function processUpdateQueue(workInProgress, props, instance, renderLanes) { - // This is always non-null on a ClassComponent or HostRoot - var queue = workInProgress.updateQueue; - hasForceUpdate = false; - { - currentlyProcessingQueue = queue.shared; - } - - var firstBaseUpdate = queue.firstBaseUpdate; - var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. - - var pendingQueue = queue.shared.pending; - - if (pendingQueue !== null) { - queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first - // and last so that it's non-circular. - - var lastPendingUpdate = pendingQueue; - var firstPendingUpdate = lastPendingUpdate.next; - lastPendingUpdate.next = null; // Append pending updates to base queue - - if (lastBaseUpdate === null) { - firstBaseUpdate = firstPendingUpdate; - } else { - lastBaseUpdate.next = firstPendingUpdate; + function hasContextChanged() { + { + return didPerformWorkStackCursor.current; + } } - lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then - // we need to transfer the updates to that queue, too. Because the base - // queue is a singly-linked list with no cycles, we can append to both - // lists and take advantage of structural sharing. - // TODO: Pass `current` as argument + function isContextProvider(type) { + { + var childContextTypes = type.childContextTypes; + return childContextTypes !== null && childContextTypes !== undefined; + } + } - var current = workInProgress.alternate; + function popContext(fiber) { + { + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor$1, fiber); + } + } - if (current !== null) { - // This is always non-null on a ClassComponent or HostRoot - var currentQueue = current.updateQueue; - var currentLastBaseUpdate = currentQueue.lastBaseUpdate; + function popTopLevelContextObject(fiber) { + { + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor$1, fiber); + } + } - if (currentLastBaseUpdate !== lastBaseUpdate) { - if (currentLastBaseUpdate === null) { - currentQueue.firstBaseUpdate = firstPendingUpdate; - } else { - currentLastBaseUpdate.next = firstPendingUpdate; + function pushTopLevelContextObject(fiber, context, didChange) { + { + if (contextStackCursor$1.current !== emptyContextObject) { + throw new Error( + "Unexpected context found on stack. " + + "This error is likely caused by a bug in React. Please file an issue." + ); } - currentQueue.lastBaseUpdate = lastPendingUpdate; + push(contextStackCursor$1, context, fiber); + push(didPerformWorkStackCursor, didChange, fiber); } } - } // These values may change as we process the queue. - - if (firstBaseUpdate !== null) { - // Iterate through the list of updates to compute the result. - var newState = queue.baseState; // TODO: Don't need to accumulate this. Instead, we can remove renderLanes - // from the original lanes. - var newLanes = NoLanes; - var newBaseState = null; - var newFirstBaseUpdate = null; - var newLastBaseUpdate = null; - var update = firstBaseUpdate; - - do { - // An extra OffscreenLane bit is added to updates that were made to - // a hidden tree, so that we can distinguish them from updates that were - // already there when the tree was hidden. - var updateLane = removeLanes(update.lane, OffscreenLane); - var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then - // it's not a "base" update and we should disregard the extra base lanes - // that were added to renderLanes when we entered the Offscreen tree. - - var shouldSkipUpdate = isHiddenUpdate - ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) - : !isSubsetOfLanes(renderLanes, updateLane); - - if (shouldSkipUpdate) { - // Priority is insufficient. Skip this update. If this is the first - // skipped update, the previous update/state is the new base - // update/state. - var clone = { - lane: updateLane, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }; - - if (newLastBaseUpdate === null) { - newFirstBaseUpdate = newLastBaseUpdate = clone; - newBaseState = newState; - } else { - newLastBaseUpdate = newLastBaseUpdate.next = clone; - } // Update the remaining priority in the queue. - - newLanes = mergeLanes(newLanes, updateLane); - } else { - // This update does have sufficient priority. - if (newLastBaseUpdate !== null) { - var _clone = { - // This update is going to be committed so we never want uncommit - // it. Using NoLane works because 0 is a subset of all bitmasks, so - // this will never be skipped by the check above. - lane: NoLane, - tag: update.tag, - payload: update.payload, - // When this update is rebased, we should not fire its - // callback again. - callback: null, - next: null - }; - newLastBaseUpdate = newLastBaseUpdate.next = _clone; - } // Process this update. + function processChildContext(fiber, type, parentContext) { + { + var instance = fiber.stateNode; + var childContextTypes = type.childContextTypes; // TODO (bvaughn) Replace this behavior with an invariant() in the future. + // It has only been added in Fiber to match the (unintentional) behavior in Stack. - newState = getStateFromUpdate( - workInProgress, - queue, - update, - newState, - props, - instance - ); - var callback = update.callback; + if (typeof instance.getChildContext !== "function") { + { + var componentName = getComponentNameFromFiber(fiber) || "Unknown"; - if (callback !== null) { - workInProgress.flags |= Callback; + if (!warnedAboutMissingGetChildContext[componentName]) { + warnedAboutMissingGetChildContext[componentName] = true; - if (isHiddenUpdate) { - workInProgress.flags |= Visibility; + 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 + ); + } } - var callbacks = queue.callbacks; - - if (callbacks === null) { - queue.callbacks = [callback]; - } else { - callbacks.push(callback); - } + return parentContext; } - } // $FlowFixMe[incompatible-type] we bail out when we get a null - - update = update.next; - - if (update === null) { - pendingQueue = queue.shared.pending; - - if (pendingQueue === null) { - break; - } else { - // An update was scheduled from inside a reducer. Add the new - // pending updates to the end of the list and keep processing. - var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we - // unravel them when transferring them to the base queue. - - var _firstPendingUpdate = _lastPendingUpdate.next; - _lastPendingUpdate.next = null; - update = _firstPendingUpdate; - queue.lastBaseUpdate = _lastPendingUpdate; - queue.shared.pending = null; - } - } - } while (true); - - if (newLastBaseUpdate === null) { - newBaseState = newState; - } - - queue.baseState = newBaseState; - queue.firstBaseUpdate = newFirstBaseUpdate; - queue.lastBaseUpdate = newLastBaseUpdate; - - if (firstBaseUpdate === null) { - // `queue.lanes` is used for entangling transitions. We can set it back to - // zero once the queue is empty. - queue.shared.lanes = NoLanes; - } // Set the remaining expiration time to be whatever is remaining in the queue. - // This should be fine because the only two other things that contribute to - // expiration time are props and context. We're already in the middle of the - // begin phase by the time we start processing the queue, so we've already - // dealt with the props. Context in components that specify - // shouldComponentUpdate is tricky; but we'll have to account for - // that regardless. - - markSkippedUpdateLanes(newLanes); - workInProgress.lanes = newLanes; - workInProgress.memoizedState = newState; - } - - { - currentlyProcessingQueue = null; - } -} - -function callCallback(callback, context) { - if (typeof callback !== "function") { - throw new Error( - "Invalid argument passed as callback. Expected a function. Instead " + - ("received: " + callback) - ); - } - - callback.call(context); -} - -function resetHasForceUpdateBeforeProcessing() { - hasForceUpdate = false; -} -function checkHasForceUpdateAfterProcessing() { - return hasForceUpdate; -} -function deferHiddenCallbacks(updateQueue) { - // When an update finishes on a hidden component, its callback should not - // be fired until/unless the component is made visible again. Stash the - // callback on the shared queue object so it can be fired later. - var newHiddenCallbacks = updateQueue.callbacks; - if (newHiddenCallbacks !== null) { - var existingHiddenCallbacks = updateQueue.shared.hiddenCallbacks; + var childContext = instance.getChildContext(); - if (existingHiddenCallbacks === null) { - updateQueue.shared.hiddenCallbacks = newHiddenCallbacks; - } else { - updateQueue.shared.hiddenCallbacks = - existingHiddenCallbacks.concat(newHiddenCallbacks); - } - } -} -function commitHiddenCallbacks(updateQueue, context) { - // This component is switching from hidden -> visible. Commit any callbacks - // that were previously deferred. - var hiddenCallbacks = updateQueue.shared.hiddenCallbacks; + for (var contextKey in childContext) { + if (!(contextKey in childContextTypes)) { + throw new Error( + (getComponentNameFromFiber(fiber) || "Unknown") + + '.getChildContext(): key "' + + contextKey + + '" is not defined in childContextTypes.' + ); + } + } - if (hiddenCallbacks !== null) { - updateQueue.shared.hiddenCallbacks = null; + { + var name = getComponentNameFromFiber(fiber) || "Unknown"; + checkPropTypes( + childContextTypes, + childContext, + "child context", + name + ); + } - for (var i = 0; i < hiddenCallbacks.length; i++) { - var callback = hiddenCallbacks[i]; - callCallback(callback, context); + return assign({}, parentContext, childContext); + } } - } -} -function commitCallbacks(updateQueue, context) { - var callbacks = updateQueue.callbacks; - if (callbacks !== null) { - updateQueue.callbacks = null; - - for (var i = 0; i < callbacks.length; i++) { - var callback = callbacks[i]; - callCallback(callback, context); + function pushContextProvider(workInProgress) { + { + var instance = workInProgress.stateNode; // We push the context as early as possible to ensure stack integrity. + // If the instance does not exist yet, we will push null at first, + // and replace it on the stack later when invalidating the context. + + var memoizedMergedChildContext = + (instance && instance.__reactInternalMemoizedMergedChildContext) || + emptyContextObject; // Remember the parent context so we can merge with it later. + // Inherit the parent's did-perform-work value to avoid inadvertently blocking updates. + + previousContext = contextStackCursor$1.current; + push(contextStackCursor$1, memoizedMergedChildContext, workInProgress); + push( + didPerformWorkStackCursor, + didPerformWorkStackCursor.current, + workInProgress + ); + return true; + } } - } -} - -/** - * Performs equality by iterating through keys on an object and returning false - * when any key has values which are not strictly equal between the arguments. - * Returns true when the values of all keys are strictly equal. - */ - -function shallowEqual(objA, objB) { - if (objectIs(objA, objB)) { - return true; - } - if ( - typeof objA !== "object" || - objA === null || - typeof objB !== "object" || - objB === null - ) { - return false; - } + function invalidateContextProvider(workInProgress, type, didChange) { + { + var instance = workInProgress.stateNode; - var keysA = Object.keys(objA); - var keysB = Object.keys(objB); + if (!instance) { + 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." + ); + } - if (keysA.length !== keysB.length) { - return false; - } // Test for A's keys different from B. + if (didChange) { + // Merge parent and own context. + // Skip this if we're not updating due to sCU. + // This avoids unnecessarily recomputing memoized values. + var mergedContext = processChildContext( + workInProgress, + type, + previousContext + ); + instance.__reactInternalMemoizedMergedChildContext = mergedContext; // Replace the old (or empty) context with the new one. + // It is important to unwind the context in the reverse order. - for (var i = 0; i < keysA.length; i++) { - var currentKey = keysA[i]; + pop(didPerformWorkStackCursor, workInProgress); + pop(contextStackCursor$1, workInProgress); // Now push the new context and mark that it has changed. - if ( - !hasOwnProperty.call(objB, currentKey) || // $FlowFixMe[incompatible-use] lost refinement of `objB` - !objectIs(objA[currentKey], objB[currentKey]) - ) { - return false; + push(contextStackCursor$1, mergedContext, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); + } else { + pop(didPerformWorkStackCursor, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); + } + } } - } - - return true; -} - -function describeFiber(fiber) { - switch (fiber.tag) { - case HostHoistable: - case HostSingleton: - case HostComponent: - return describeBuiltInComponentFrame(fiber.type); - case LazyComponent: - return describeBuiltInComponentFrame("Lazy"); - - case SuspenseComponent: - return describeBuiltInComponentFrame("Suspense"); - - case SuspenseListComponent: - return describeBuiltInComponentFrame("SuspenseList"); - - case FunctionComponent: - case IndeterminateComponent: - case SimpleMemoComponent: - return describeFunctionComponentFrame(fiber.type); - - case ForwardRef: - return describeFunctionComponentFrame(fiber.type.render); + function findCurrentUnmaskedContext(fiber) { + { + // Currently this is only used with renderSubtreeIntoContainer; not sure if it + // makes sense elsewhere + if (!isFiberMounted(fiber) || fiber.tag !== ClassComponent) { + 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." + ); + } - case ClassComponent: - return describeClassComponentFrame(fiber.type); + var node = fiber; - default: - return ""; - } -} + do { + switch (node.tag) { + case HostRoot: + return node.stateNode.context; -function getStackByFiberInDevAndProd(workInProgress) { - try { - var info = ""; - var node = workInProgress; + case ClassComponent: { + var Component = node.type; - do { - info += describeFiber(node); // $FlowFixMe[incompatible-type] we bail out when we get a null + if (isContextProvider(Component)) { + return node.stateNode.__reactInternalMemoizedMergedChildContext; + } - node = node.return; - } while (node); + break; + } + } // $FlowFixMe[incompatible-type] we bail out when we get a null - return info; - } catch (x) { - return "\nError generating stack: " + x.message + "\n" + x.stack; - } -} + node = node.return; + } while (node !== null); -var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; -var current = null; -var isRendering = false; -function getCurrentFiberOwnerNameInDevOrNull() { - { - if (current === null) { - return null; + throw new Error( + "Found unexpected detached subtree parent. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } } - var owner = current._debugOwner; - - if (owner !== null && typeof owner !== "undefined") { - return getComponentNameFromFiber(owner); + // We use the existence of the state object as an indicator that the component + // is hidden. + var OffscreenVisible = + /* */ + 1; + var OffscreenDetached = + /* */ + 2; + var OffscreenPassiveEffectsConnected = + /* */ + 4; + function isOffscreenManual(offscreenFiber) { + return ( + offscreenFiber.memoizedProps !== null && + offscreenFiber.memoizedProps.mode === "manual" + ); } - } - return null; -} + /** + * inlined Object.is polyfill to avoid requiring consumers ship their own + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is + */ + function is(x, y) { + return ( + (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare + ); + } -function getCurrentFiberStackInDev() { - { - if (current === null) { - return ""; - } // Safe because if current fiber exists, we are reconciling, - // and it is guaranteed to be the work-in-progress version. + var objectIs = typeof Object.is === "function" ? Object.is : is; // $FlowFixMe[method-unbinding] - return getStackByFiberInDevAndProd(current); - } -} + var nativeConsole = console; + var nativeConsoleLog = null; + var pendingGroupArgs = []; + var printedGroupIndex = -1; -function resetCurrentFiber() { - { - ReactDebugCurrentFrame.getCurrentStack = null; - current = null; - isRendering = false; - } -} -function setCurrentFiber(fiber) { - { - ReactDebugCurrentFrame.getCurrentStack = - fiber === null ? null : getCurrentFiberStackInDev; - current = fiber; - isRendering = false; - } -} -function getCurrentFiber() { - { - return current; - } -} -function setIsRendering(rendering) { - { - isRendering = rendering; - } -} + function formatLanes(laneOrLanes) { + return "0b" + laneOrLanes.toString(2).padStart(31, "0"); + } -var ReactStrictModeWarnings = { - recordUnsafeLifecycleWarnings: function (fiber, instance) {}, - flushPendingUnsafeLifecycleWarnings: function () {}, - recordLegacyContextWarning: function (fiber, instance) {}, - flushLegacyContextWarning: function () {}, - discardPendingWarnings: function () {} -}; + function group() { + for ( + var _len = arguments.length, groupArgs = new Array(_len), _key = 0; + _key < _len; + _key++ + ) { + groupArgs[_key] = arguments[_key]; + } -{ - var findStrictRoot = function (fiber) { - var maybeStrictRoot = null; - var node = fiber; + pendingGroupArgs.push(groupArgs); - while (node !== null) { - if (node.mode & StrictLegacyMode) { - maybeStrictRoot = node; + if (nativeConsoleLog === null) { + nativeConsoleLog = nativeConsole.log; + nativeConsole.log = log; } - - node = node.return; } - return maybeStrictRoot; - }; - - var setToSortedString = function (set) { - var array = []; - set.forEach(function (value) { - array.push(value); - }); - return array.sort().join(", "); - }; - - var pendingComponentWillMountWarnings = []; - var pendingUNSAFE_ComponentWillMountWarnings = []; - var pendingComponentWillReceivePropsWarnings = []; - var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - var pendingComponentWillUpdateWarnings = []; - var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. + function groupEnd() { + pendingGroupArgs.pop(); - var didWarnAboutUnsafeLifecycles = new Set(); + while (printedGroupIndex >= pendingGroupArgs.length) { + nativeConsole.groupEnd(); + printedGroupIndex--; + } - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function ( - fiber, - instance - ) { - // Dedupe strategy: Warn once per component. - if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { - return; + if (pendingGroupArgs.length === 0) { + nativeConsole.log = nativeConsoleLog; + nativeConsoleLog = null; + } } - if ( - typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - pendingComponentWillMountWarnings.push(fiber); - } + function log() { + if (printedGroupIndex < pendingGroupArgs.length - 1) { + for (var i = printedGroupIndex + 1; i < pendingGroupArgs.length; i++) { + var groupArgs = pendingGroupArgs[i]; + nativeConsole.group.apply(nativeConsole, groupArgs); + } - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillMount === "function" - ) { - pendingUNSAFE_ComponentWillMountWarnings.push(fiber); - } + printedGroupIndex = pendingGroupArgs.length - 1; + } - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== true - ) { - pendingComponentWillReceivePropsWarnings.push(fiber); + if (typeof nativeConsoleLog === "function") { + nativeConsoleLog.apply(void 0, arguments); + } else { + nativeConsole.log.apply(nativeConsole, arguments); + } } - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); + var REACT_LOGO_STYLE = + "background-color: #20232a; color: #61dafb; padding: 0 2px;"; + function logCommitStarted(lanes) { + { + if (enableDebugTracing) { + group( + "%c\u269B\uFE0F%c commit%c (" + formatLanes(lanes) + ")", + REACT_LOGO_STYLE, + "", + "font-weight: normal;" + ); + } + } } - - if ( - typeof instance.componentWillUpdate === "function" && - instance.componentWillUpdate.__suppressDeprecationWarning !== true - ) { - pendingComponentWillUpdateWarnings.push(fiber); + function logCommitStopped() { + { + if (enableDebugTracing) { + groupEnd(); + } + } } + var PossiblyWeakMap$1 = typeof WeakMap === "function" ? WeakMap : Map; // $FlowFixMe[incompatible-type]: Flow cannot handle polymorphic WeakMaps - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillUpdate === "function" - ) { - pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); - } - }; + var wakeableIDs = new PossiblyWeakMap$1(); + var wakeableID = 0; - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function () { - // We do an initial pass to gather component names - var componentWillMountUniqueNames = new Set(); + function getWakeableID(wakeable) { + if (!wakeableIDs.has(wakeable)) { + wakeableIDs.set(wakeable, wakeableID++); + } - if (pendingComponentWillMountWarnings.length > 0) { - pendingComponentWillMountWarnings.forEach(function (fiber) { - componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillMountWarnings = []; + return wakeableIDs.get(wakeable); } - var UNSAFE_componentWillMountUniqueNames = new Set(); - - if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { - pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) { - UNSAFE_componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillMountWarnings = []; + function logComponentSuspended(componentName, wakeable) { + { + if (enableDebugTracing) { + var id = getWakeableID(wakeable); + var display = wakeable.displayName || wakeable; + log( + "%c\u269B\uFE0F%c " + componentName + " suspended", + REACT_LOGO_STYLE, + "color: #80366d; font-weight: bold;", + id, + display + ); + wakeable.then( + function () { + log( + "%c\u269B\uFE0F%c " + componentName + " resolved", + REACT_LOGO_STYLE, + "color: #80366d; font-weight: bold;", + id, + display + ); + }, + function () { + log( + "%c\u269B\uFE0F%c " + componentName + " rejected", + REACT_LOGO_STYLE, + "color: #80366d; font-weight: bold;", + id, + display + ); + } + ); + } + } } - - var componentWillReceivePropsUniqueNames = new Set(); - - if (pendingComponentWillReceivePropsWarnings.length > 0) { - pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { - componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillReceivePropsWarnings = []; + function logLayoutEffectsStarted(lanes) { + { + if (enableDebugTracing) { + group( + "%c\u269B\uFE0F%c layout effects%c (" + formatLanes(lanes) + ")", + REACT_LOGO_STYLE, + "", + "font-weight: normal;" + ); + } + } } - - var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); - - if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(function (fiber) { - UNSAFE_componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + function logLayoutEffectsStopped() { + { + if (enableDebugTracing) { + groupEnd(); + } + } } - - var componentWillUpdateUniqueNames = new Set(); - - if (pendingComponentWillUpdateWarnings.length > 0) { - pendingComponentWillUpdateWarnings.forEach(function (fiber) { - componentWillUpdateUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillUpdateWarnings = []; + function logPassiveEffectsStarted(lanes) { + { + if (enableDebugTracing) { + group( + "%c\u269B\uFE0F%c passive effects%c (" + formatLanes(lanes) + ")", + REACT_LOGO_STYLE, + "", + "font-weight: normal;" + ); + } + } + } + function logPassiveEffectsStopped() { + { + if (enableDebugTracing) { + groupEnd(); + } + } + } + function logRenderStarted(lanes) { + { + if (enableDebugTracing) { + group( + "%c\u269B\uFE0F%c render%c (" + formatLanes(lanes) + ")", + REACT_LOGO_STYLE, + "", + "font-weight: normal;" + ); + } + } + } + function logRenderStopped() { + { + if (enableDebugTracing) { + groupEnd(); + } + } + } + function logForceUpdateScheduled(componentName, lane) { + { + if (enableDebugTracing) { + log( + "%c\u269B\uFE0F%c " + + componentName + + " forced update %c(" + + formatLanes(lane) + + ")", + REACT_LOGO_STYLE, + "color: #db2e1f; font-weight: bold;", + "" + ); + } + } + } + function logStateUpdateScheduled(componentName, lane, payloadOrAction) { + { + if (enableDebugTracing) { + log( + "%c\u269B\uFE0F%c " + + componentName + + " updated state %c(" + + formatLanes(lane) + + ")", + REACT_LOGO_STYLE, + "color: #01a252; font-weight: bold;", + "", + payloadOrAction + ); + } + } } - var UNSAFE_componentWillUpdateUniqueNames = new Set(); - - if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { - pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function (fiber) { - UNSAFE_componentWillUpdateUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillUpdateWarnings = []; - } // Finally, we flush all the warnings - // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' - - if (UNSAFE_componentWillMountUniqueNames.size > 0) { - var sortedNames = setToSortedString(UNSAFE_componentWillMountUniqueNames); - - 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 - ); + // This is imported by the event replaying implementation in React DOM. It's + // in a separate file to break a circular dependency between the renderer and + // the reconciler. + function isRootDehydrated(root) { + var currentState = root.current.memoizedState; + return currentState.isDehydrated; } - if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames = setToSortedString( - UNSAFE_componentWillReceivePropsUniqueNames - ); + var contextStackCursor = createCursor(null); + var contextFiberStackCursor = createCursor(null); + var rootInstanceStackCursor = createCursor(null); // Represents the nearest host transition provider (in React DOM, a ) - 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 - ); - } + function requiredContext(c) { + { + if (c === null) { + error( + "Expected host context to exist. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + } + } - if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { - var _sortedNames2 = setToSortedString( - UNSAFE_componentWillUpdateUniqueNames - ); + return c; + } - 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 - ); + function getRootHostContainer() { + var rootInstance = requiredContext(rootInstanceStackCursor.current); + return rootInstance; } - if (componentWillMountUniqueNames.size > 0) { - var _sortedNames3 = setToSortedString(componentWillMountUniqueNames); + function pushHostContainer(fiber, nextRootInstance) { + // Push current root instance onto the stack; + // This allows us to reset root when portals are popped. + push(rootInstanceStackCursor, nextRootInstance, fiber); // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. - 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 - ); - } + push(contextFiberStackCursor, fiber, fiber); // Finally, we need to push the host context to the stack. + // However, we can't just call getRootHostContext() and push it because + // we'd have a different number of entries on the stack depending on + // whether getRootHostContext() throws somewhere in renderer code or not. + // So we push an empty value first. This lets us safely unwind on errors. - if (componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames4 = setToSortedString( - componentWillReceivePropsUniqueNames - ); + push(contextStackCursor, null, fiber); + var nextRootContext = getRootHostContext(); // Now that we know this function doesn't throw, replace it. - 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 - ); + pop(contextStackCursor, fiber); + push(contextStackCursor, nextRootContext, fiber); } - if (componentWillUpdateUniqueNames.size > 0) { - var _sortedNames5 = setToSortedString(componentWillUpdateUniqueNames); + function popHostContainer(fiber) { + pop(contextStackCursor, fiber); + pop(contextFiberStackCursor, fiber); + pop(rootInstanceStackCursor, fiber); + } - 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 - ); + function getHostContext() { + var context = requiredContext(contextStackCursor.current); + return context; } - }; - var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. + function pushHostContext(fiber) { + var context = requiredContext(contextStackCursor.current); + var nextContext = getChildHostContext(); // Don't push this Fiber's context unless it's unique. - var didWarnAboutLegacyContext = new Set(); + if (context !== nextContext) { + // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. + push(contextFiberStackCursor, fiber, fiber); + push(contextStackCursor, nextContext, fiber); + } + } - ReactStrictModeWarnings.recordLegacyContextWarning = function ( - fiber, - instance - ) { - var strictRoot = findStrictRoot(fiber); + function popHostContext(fiber) { + if (contextFiberStackCursor.current === fiber) { + // Do not pop unless this Fiber provided the current context. + // pushHostContext() only pushes Fibers that provide unique contexts. + pop(contextStackCursor, fiber); + pop(contextFiberStackCursor, fiber); + } + } - if (strictRoot === null) { - 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." - ); + var isHydrating = false; // This flag allows for warning supression when we expect there to be mismatches + // due to earlier mismatches or a suspended fiber. - return; - } // Dedup strategy: Warn once per component. + var didSuspendOrErrorDEV = false; // Hydration errors that were thrown inside this boundary - if (didWarnAboutLegacyContext.has(fiber.type)) { - return; + var hydrationErrors = null; + function didSuspendOrErrorWhileHydratingDEV() { + { + return didSuspendOrErrorDEV; + } } - var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); - - if ( - fiber.type.contextTypes != null || - fiber.type.childContextTypes != null || - (instance !== null && typeof instance.getChildContext === "function") - ) { - if (warningsForRoot === undefined) { - warningsForRoot = []; - pendingLegacyContextWarning.set(strictRoot, warningsForRoot); + function prepareToHydrateHostInstance(fiber, hostContext) { + { + throw new Error( + "Expected prepareToHydrateHostInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); } - - warningsForRoot.push(fiber); } - }; - ReactStrictModeWarnings.flushLegacyContextWarning = function () { - pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) { - if (fiberArray.length === 0) { - return; + function prepareToHydrateHostTextInstance(fiber) { + { + throw new Error( + "Expected prepareToHydrateHostTextInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); } + } - var firstFiber = fiberArray[0]; - var uniqueNames = new Set(); - fiberArray.forEach(function (fiber) { - uniqueNames.add(getComponentNameFromFiber(fiber) || "Component"); - didWarnAboutLegacyContext.add(fiber.type); - }); - var sortedNames = setToSortedString(uniqueNames); - - try { - setCurrentFiber(firstFiber); - - 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 + function prepareToHydrateHostSuspenseInstance(fiber) { + { + throw new Error( + "Expected prepareToHydrateHostSuspenseInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." ); - } finally { - resetCurrentFiber(); } - }); - }; - - ReactStrictModeWarnings.discardPendingWarnings = function () { - pendingComponentWillMountWarnings = []; - pendingUNSAFE_ComponentWillMountWarnings = []; - pendingComponentWillReceivePropsWarnings = []; - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - pendingComponentWillUpdateWarnings = []; - pendingUNSAFE_ComponentWillUpdateWarnings = []; - pendingLegacyContextWarning = new Map(); - }; -} - -/* - * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol - * and Temporal.* types. See https://github.com/facebook/react/pull/22064. - * - * The functions in this module will throw an easier-to-understand, - * easier-to-debug exception with a clear errors message message explaining the - * problem. (Instead of a confusing exception thrown inside the implementation - * of the `value` object). - */ -// $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. -function typeName(value) { - { - // toStringTag is needed for namespaced types like Temporal.Instant - var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; - var type = - (hasToStringTag && value[Symbol.toStringTag]) || - value.constructor.name || - "Object"; // $FlowFixMe[incompatible-return] - - return type; - } -} // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - -function willCoercionThrow(value) { - { - try { - testStringCoercion(value); - return false; - } catch (e) { - return true; } - } -} -function testStringCoercion(value) { - // If you ended up here by following an exception call stack, here's what's - // happened: you supplied an object or symbol value to React (as a prop, key, - // DOM attribute, CSS property, string ref, etc.) and when React tried to - // coerce it to a string using `'' + value`, an exception was thrown. - // - // The most common types that will cause this exception are `Symbol` instances - // and Temporal objects like `Temporal.Instant`. But any object that has a - // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this - // exception. (Library authors do this to prevent users from using built-in - // numeric operators like `+` or comparison operators like `>=` because custom - // methods are needed to perform accurate arithmetic or comparison.) - // - // To fix the problem, coerce this object or symbol value to a string before - // passing it to React. The most reliable way is usually `String(value)`. - // - // To find which value is throwing, check the browser or debugger console. - // Before this exception was thrown, there should be `console.error` output - // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the - // problem and how that type was used: key, atrribute, input value prop, etc. - // In most cases, this console output also shows the component and its - // ancestor components where the exception happened. - // - // eslint-disable-next-line react-internal/safe-string-coercion - return "" + value; -} -function checkPropStringCoercion(value, propName) { - { - if (willCoercionThrow(value)) { - error( - "The provided `%s` prop is an unsupported type %s." + - " This value must be coerced to a string before using it here.", - propName, - typeName(value) - ); + function popHydrationState(fiber) { + { + return false; + } + } - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + function upgradeHydrationErrorsToRecoverable() { + if (hydrationErrors !== null) { + // Successfully completed a forced client render. The errors that occurred + // during the hydration attempt are now recovered. We will log them in + // commit phase, once the entire tree has finished. + queueRecoverableErrors(hydrationErrors); + hydrationErrors = null; + } } - } -} -var ReactCurrentActQueue$3 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we -// detect this is caught by userspace, we'll log a warning in development. - -var SuspenseException = new Error( - "Suspense Exception: This is not a real error! It's an implementation " + - "detail of `use` to interrupt the current render. You must either " + - "rethrow it immediately, or move the `use` call outside of the " + - "`try/catch` block. Capturing without rethrowing will lead to " + - "unexpected behavior.\n\n" + - "To handle async errors, wrap your component in an error boundary, or " + - "call the promise's `.catch` method and pass the result to `use`" -); -var SuspenseyCommitException = new Error( - "Suspense Exception: This is not a real error, and should not leak into " + - "userspace. If you're seeing this, it's likely a bug in React." -); // This is a noop thenable that we use to trigger a fallback in throwException. -// TODO: It would be better to refactor throwException into multiple functions -// so we can trigger a fallback directly without having to check the type. But -// for now this will do. - -var noopSuspenseyCommitThenable = { - then: function () { - { - error( - "Internal React error: A listener was unexpectedly attached to a " + - '"noop" thenable. This is a bug in React. Please file an issue.' - ); + function getIsHydrating() { + return isHydrating; } - } -}; -function createThenableState() { - // The ThenableState is created the first time a component suspends. If it - // suspends again, we'll reuse the same state. - return []; -} -function isThenableResolved(thenable) { - var status = thenable.status; - return status === "fulfilled" || status === "rejected"; -} -function noop() {} - -function trackUsedThenable(thenableState, thenable, index) { - if (ReactCurrentActQueue$3.current !== null) { - ReactCurrentActQueue$3.didUsePromise = true; - } - - var previous = thenableState[index]; - - if (previous === undefined) { - thenableState.push(thenable); - } else { - if (previous !== thenable) { - // Reuse the previous thenable, and drop the new one. We can assume - // they represent the same value, because components are idempotent. - // Avoid an unhandled rejection errors for the Promises that we'll - // intentionally ignore. - thenable.then(noop, noop); - thenable = previous; - } - } // We use an expando to track the status and result of a thenable so that we - // can synchronously unwrap the value. Think of this as an extension of the - // Promise API, or a custom interface that is a superset of Thenable. - // - // If the thenable doesn't have a status, set it to "pending" and attach - // a listener that will update its status and result when it resolves. - - switch (thenable.status) { - case "fulfilled": { - var fulfilledValue = thenable.value; - return fulfilledValue; - } - - case "rejected": { - var rejectedError = thenable.reason; - checkIfUseWrappedInAsyncCatch(rejectedError); - throw rejectedError; - } - - default: { - if (typeof thenable.status === "string") { - // Only instrument the thenable if the status if not defined. If - // it's defined, but an unknown value, assume it's been instrumented by - // some custom userspace implementation. We treat it as "pending". - // Attach a dummy listener, to ensure that any lazy initialization can - // happen. Flight lazily parses JSON when the value is actually awaited. - thenable.then(noop, noop); + function queueHydrationError(error) { + if (hydrationErrors === null) { + hydrationErrors = [error]; } else { - // This is an uncached thenable that we haven't seen before. - // Detect infinite ping loops caused by uncached promises. - var root = getWorkInProgressRoot(); - - if (root !== null && root.shellSuspendCounter > 100) { - // This root has suspended repeatedly in the shell without making any - // progress (i.e. committing something). This is highly suggestive of - // an infinite ping loop, often caused by an accidental Async Client - // Component. - // - // During a transition, we can suspend the work loop until the promise - // to resolve, but this is a sync render, so that's not an option. We - // also can't show a fallback, because none was provided. So our last - // resort is to throw an error. - // - // TODO: Remove this error in a future release. Other ways of handling - // this case include forcing a concurrent render, or putting the whole - // root into offscreen mode. - throw new Error( - "async/await is not yet supported in Client Components, only " + - "Server Components. This error is often caused by accidentally " + - "adding `'use client'` to a module that was originally written " + - "for the server." - ); - } - - var pendingThenable = thenable; - pendingThenable.status = "pending"; - pendingThenable.then( - function (fulfilledValue) { - if (thenable.status === "pending") { - var fulfilledThenable = thenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = fulfilledValue; - } - }, - function (error) { - if (thenable.status === "pending") { - var rejectedThenable = thenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = error; - } - } - ); // Check one more time in case the thenable resolved synchronously. - - switch (thenable.status) { - case "fulfilled": { - var fulfilledThenable = thenable; - return fulfilledThenable.value; + hydrationErrors.push(error); + } + } + + // we wait until the current render is over (either finished or interrupted) + // before adding it to the fiber/hook queue. Push to this array so we can + // access the queue, fiber, update, et al later. + + var concurrentQueues = []; + var concurrentQueuesIndex = 0; + var concurrentlyUpdatedLanes = NoLanes; + function finishQueueingConcurrentUpdates() { + var endIndex = concurrentQueuesIndex; + concurrentQueuesIndex = 0; + concurrentlyUpdatedLanes = NoLanes; + var i = 0; + + while (i < endIndex) { + var fiber = concurrentQueues[i]; + concurrentQueues[i++] = null; + var queue = concurrentQueues[i]; + concurrentQueues[i++] = null; + var update = concurrentQueues[i]; + concurrentQueues[i++] = null; + var lane = concurrentQueues[i]; + concurrentQueues[i++] = null; + + if (queue !== null && update !== null) { + var pending = queue.pending; + + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; } - case "rejected": { - var rejectedThenable = thenable; - var _rejectedError = rejectedThenable.reason; - checkIfUseWrappedInAsyncCatch(_rejectedError); - throw _rejectedError; - } + queue.pending = update; } - } // Suspend. - // - // Throwing here is an implementation detail that allows us to unwind the - // call stack. But we shouldn't allow it to leak into userspace. Throw an - // opaque placeholder value instead of the actual thenable. If it doesn't - // get captured by the work loop, log a warning, because that means - // something in userspace must have caught it. - suspendedThenable = thenable; - - { - needsToResetSuspendedThenableDEV = true; + if (lane !== NoLane) { + markUpdateLaneFromFiberToRoot(fiber, update, lane); + } } - - throw SuspenseException; } - } -} -// passed to the rest of the Suspense implementation — which, for historical -// reasons, expects to receive a thenable. - -var suspendedThenable = null; -var needsToResetSuspendedThenableDEV = false; -function getSuspendedThenable() { - // This is called right after `use` suspends by throwing an exception. `use` - // throws an opaque value instead of the thenable itself so that it can't be - // caught in userspace. Then the work loop accesses the actual thenable using - // this function. - if (suspendedThenable === null) { - throw new Error( - "Expected a suspended thenable. This is a bug in React. Please file " + - "an issue." - ); - } - - var thenable = suspendedThenable; - suspendedThenable = null; - - { - needsToResetSuspendedThenableDEV = false; - } - - return thenable; -} -function checkIfUseWrappedInTryCatch() { - { - // This was set right before SuspenseException was thrown, and it should - // have been cleared when the exception was handled. If it wasn't, - // it must have been caught by userspace. - if (needsToResetSuspendedThenableDEV) { - needsToResetSuspendedThenableDEV = false; - return true; + function getConcurrentlyUpdatedLanes() { + return concurrentlyUpdatedLanes; } - } - return false; -} -function checkIfUseWrappedInAsyncCatch(rejectedReason) { - // This check runs in prod, too, because it prevents a more confusing - // downstream error, where SuspenseException is caught by a promise and - // thrown asynchronously. - // TODO: Another way to prevent SuspenseException from leaking into an async - // execution context is to check the dispatcher every time `use` is called, - // or some equivalent. That might be preferable for other reasons, too, since - // it matches how we prevent similar mistakes for other hooks. - if (rejectedReason === SuspenseException) { - throw new Error( - "Hooks are not supported inside an async component. This " + - "error is often caused by accidentally adding `'use client'` " + - "to a module that was originally written for the server." - ); - } -} + function enqueueUpdate$1(fiber, queue, update, lane) { + // Don't update the `childLanes` on the return path yet. If we already in + // the middle of rendering, wait until after it has completed. + concurrentQueues[concurrentQueuesIndex++] = fiber; + concurrentQueues[concurrentQueuesIndex++] = queue; + concurrentQueues[concurrentQueuesIndex++] = update; + concurrentQueues[concurrentQueuesIndex++] = lane; + concurrentlyUpdatedLanes = mergeLanes(concurrentlyUpdatedLanes, lane); // The fiber's `lane` field is used in some places to check if any work is + // scheduled, to perform an eager bailout, so we need to update it immediately. + // TODO: We should probably move this to the "shared" queue instead. -var thenableState$1 = null; -var thenableIndexCounter$1 = 0; -var didWarnAboutMaps; -var didWarnAboutGenerators; -var didWarnAboutStringRefs; -var ownerHasKeyUseWarning; -var ownerHasFunctionTypeWarning; + fiber.lanes = mergeLanes(fiber.lanes, lane); + var alternate = fiber.alternate; -var warnForMissingKey = function (child, returnFiber) {}; + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, lane); + } + } -{ - didWarnAboutMaps = false; - didWarnAboutGenerators = false; - didWarnAboutStringRefs = {}; - /** - * Warn if there's no key explicitly set on dynamic arrays of children or - * object keys are not valid. This allows us to keep track of children between - * updates. - */ + function enqueueConcurrentHookUpdate(fiber, queue, update, lane) { + var concurrentQueue = queue; + var concurrentUpdate = update; + enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); + return getRootForUpdatedFiber(fiber); + } + function enqueueConcurrentHookUpdateAndEagerlyBailout( + fiber, + queue, + update + ) { + // This function is used to queue an update that doesn't need a rerender. The + // only reason we queue it is in case there's a subsequent higher priority + // update that causes it to be rebased. + var lane = NoLane; + var concurrentQueue = queue; + var concurrentUpdate = update; + enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); // Usually we can rely on the upcoming render phase to process the concurrent + // queue. However, since this is a bail out, we're not scheduling any work + // here. So the update we just queued will leak until something else happens + // to schedule work (if ever). + // + // Check if we're currently in the middle of rendering a tree, and if not, + // process the queue immediately to prevent a leak. - ownerHasKeyUseWarning = {}; - ownerHasFunctionTypeWarning = {}; + var isConcurrentlyRendering = getWorkInProgressRoot() !== null; - warnForMissingKey = function (child, returnFiber) { - if (child === null || typeof child !== "object") { - return; + if (!isConcurrentlyRendering) { + finishQueueingConcurrentUpdates(); + } } + function enqueueConcurrentClassUpdate(fiber, queue, update, lane) { + var concurrentQueue = queue; + var concurrentUpdate = update; + enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); + return getRootForUpdatedFiber(fiber); + } + function enqueueConcurrentRenderForLane(fiber, lane) { + enqueueUpdate$1(fiber, null, null, lane); + return getRootForUpdatedFiber(fiber); + } // Calling this function outside this module should only be done for backwards + // compatibility and should always be accompanied by a warning. - if (!child._store || child._store.validated || child.key != null) { - return; + function unsafe_markUpdateLaneFromFiberToRoot(sourceFiber, lane) { + // NOTE: For Hyrum's Law reasons, if an infinite update loop is detected, it + // should throw before `markUpdateLaneFromFiberToRoot` is called. But this is + // undefined behavior and we can change it if we need to; it just so happens + // that, at the time of this writing, there's an internal product test that + // happens to rely on this. + var root = getRootForUpdatedFiber(sourceFiber); + markUpdateLaneFromFiberToRoot(sourceFiber, null, lane); + return root; } - if (typeof child._store !== "object") { - 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." - ); - } // $FlowFixMe[cannot-write] unable to narrow type from mixed to writable object + function markUpdateLaneFromFiberToRoot(sourceFiber, update, lane) { + // Update the source fiber's lanes + sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane); + var alternate = sourceFiber.alternate; - child._store.validated = true; - var componentName = getComponentNameFromFiber(returnFiber) || "Component"; + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, lane); + } // Walk the parent path to the root and update the child lanes. - if (ownerHasKeyUseWarning[componentName]) { - return; - } + var isHidden = false; + var parent = sourceFiber.return; + var node = sourceFiber; - ownerHasKeyUseWarning[componentName] = true; + while (parent !== null) { + parent.childLanes = mergeLanes(parent.childLanes, lane); + alternate = parent.alternate; - error( - "Each child in a list should have a unique " + - '"key" prop. See https://reactjs.org/link/warning-keys for ' + - "more information." - ); - }; -} + if (alternate !== null) { + alternate.childLanes = mergeLanes(alternate.childLanes, lane); + } -function isReactClass(type) { - return type.prototype && type.prototype.isReactComponent; -} + if (parent.tag === OffscreenComponent) { + // Check if this offscreen boundary is currently hidden. + // + // The instance may be null if the Offscreen parent was unmounted. Usually + // the parent wouldn't be reachable in that case because we disconnect + // fibers from the tree when they are deleted. However, there's a weird + // edge case where setState is called on a fiber that was interrupted + // before it ever mounted. Because it never mounts, it also never gets + // deleted. Because it never gets deleted, its return pointer never gets + // disconnected. Which means it may be attached to a deleted Offscreen + // parent node. (This discovery suggests it may be better for memory usage + // if we don't attach the `return` pointer until the commit phase, though + // in order to do that we'd need some other way to track the return + // pointer during the initial render, like on the stack.) + // + // This case is always accompanied by a warning, but we still need to + // account for it. (There may be other cases that we haven't discovered, + // too.) + var offscreenInstance = parent.stateNode; -function unwrapThenable(thenable) { - var index = thenableIndexCounter$1; - thenableIndexCounter$1 += 1; + if ( + offscreenInstance !== null && + !(offscreenInstance._visibility & OffscreenVisible) + ) { + isHidden = true; + } + } - if (thenableState$1 === null) { - thenableState$1 = createThenableState(); - } + node = parent; + parent = parent.return; + } - return trackUsedThenable(thenableState$1, thenable, index); -} + if (isHidden && update !== null && node.tag === HostRoot) { + var root = node.stateNode; + markHiddenUpdate(root, update, lane); + } + } -function coerceRef(returnFiber, current, element) { - var mixedRef = element.ref; + function getRootForUpdatedFiber(sourceFiber) { + // TODO: We will detect and infinite update loop and throw even if this fiber + // has already unmounted. This isn't really necessary but it happens to be the + // current behavior we've used for several release cycles. Consider not + // performing this check if the updated fiber already unmounted, since it's + // not possible for that to cause an infinite update loop. + throwIfInfiniteUpdateLoopDetected(); // When a setState happens, we must ensure the root is scheduled. Because + // update queues do not have a backpointer to the root, the only way to do + // this currently is to walk up the return path. This used to not be a big + // deal because we would have to walk up the return path to set + // the `childLanes`, anyway, but now those two traversals happen at + // different times. + // TODO: Consider adding a `root` backpointer on the update queue. - if ( - mixedRef !== null && - typeof mixedRef !== "function" && - typeof mixedRef !== "object" - ) { - { - if ( - // We warn in ReactElement.js if owner and self are equal for string refs - // because these cannot be automatically converted to an arrow function - // using a codemod. Therefore, we don't have to warn about string refs again. - !( - element._owner && - element._self && - element._owner.stateNode !== element._self - ) && // Will already throw with "Function components cannot have string refs" - !(element._owner && element._owner.tag !== ClassComponent) && // Will already warn with "Function components cannot be given refs" - !(typeof element.type === "function" && !isReactClass(element.type)) && // Will already throw with "Element ref was specified as a string (someStringRef) but no owner was set" - element._owner - ) { - var componentName = - getComponentNameFromFiber(returnFiber) || "Component"; + detectUpdateOnUnmountedFiber(sourceFiber, sourceFiber); + var node = sourceFiber; + var parent = node.return; - if (!didWarnAboutStringRefs[componentName]) { - 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 - ); + while (parent !== null) { + detectUpdateOnUnmountedFiber(sourceFiber, node); + node = parent; + parent = node.return; + } + + return node.tag === HostRoot ? node.stateNode : null; + } + + function detectUpdateOnUnmountedFiber(sourceFiber, parent) { + { + var alternate = parent.alternate; - didWarnAboutStringRefs[componentName] = true; + if ( + alternate === null && + (parent.flags & (Placement | Hydrating)) !== NoFlags$1 + ) { + warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); } } } - if (element._owner) { - var owner = element._owner; - var inst; + var UpdateState = 0; + var ReplaceState = 1; + var ForceUpdate = 2; + var CaptureUpdate = 3; // Global state that is reset at the beginning of calling `processUpdateQueue`. + // It should only be read right after calling `processUpdateQueue`, via + // `checkHasForceUpdateAfterProcessing`. - if (owner) { - var ownerFiber = owner; + var hasForceUpdate = false; + var didWarnUpdateInsideUpdate; + var currentlyProcessingQueue; - if (ownerFiber.tag !== ClassComponent) { - 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" - ); - } + { + didWarnUpdateInsideUpdate = false; + currentlyProcessingQueue = null; + } + + function initializeUpdateQueue(fiber) { + var queue = { + baseState: fiber.memoizedState, + firstBaseUpdate: null, + lastBaseUpdate: null, + shared: { + pending: null, + lanes: NoLanes, + hiddenCallbacks: null + }, + callbacks: null + }; + fiber.updateQueue = queue; + } + function cloneUpdateQueue(current, workInProgress) { + // Clone the update queue from current. Unless it's already a clone. + var queue = workInProgress.updateQueue; + var currentQueue = current.updateQueue; - inst = ownerFiber.stateNode; + if (queue === currentQueue) { + var clone = { + baseState: currentQueue.baseState, + firstBaseUpdate: currentQueue.firstBaseUpdate, + lastBaseUpdate: currentQueue.lastBaseUpdate, + shared: currentQueue.shared, + callbacks: null + }; + workInProgress.updateQueue = clone; } + } + function createUpdate(lane) { + var update = { + lane: lane, + tag: UpdateState, + payload: null, + callback: null, + next: null + }; + return update; + } + function enqueueUpdate(fiber, update, lane) { + var updateQueue = fiber.updateQueue; - if (!inst) { - throw new Error( - "Missing owner for string ref " + - mixedRef + - ". This error is likely caused by a " + - "bug in React. Please file an issue." - ); - } // Assigning this to a const so Flow knows it won't change in the closure + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return null; + } - var resolvedInst = inst; + var sharedQueue = updateQueue.shared; { - checkPropStringCoercion(mixedRef, "ref"); - } + if ( + currentlyProcessingQueue === sharedQueue && + !didWarnUpdateInsideUpdate + ) { + var componentName = getComponentNameFromFiber(fiber); - var stringRef = "" + mixedRef; // Check if previous string ref matches new string ref + 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.\n\nPlease update the following component: %s", + componentName + ); - if ( - current !== null && - current.ref !== null && - typeof current.ref === "function" && - current.ref._stringRef === stringRef - ) { - return current.ref; + didWarnUpdateInsideUpdate = true; + } } - var ref = function (value) { - var refs = resolvedInst.refs; + if (isUnsafeClassRenderPhaseUpdate()) { + // This is an unsafe render phase update. Add directly to the update + // queue so we can process it immediately during the current render. + var pending = sharedQueue.pending; - if (value === null) { - delete refs[stringRef]; + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; } else { - refs[stringRef] = value; + update.next = pending.next; + pending.next = update; } - }; - ref._stringRef = stringRef; - return ref; - } else { - if (typeof mixedRef !== "string") { - throw new Error( - "Expected ref to be a function, a string, an object returned by React.createRef(), or null." - ); - } + sharedQueue.pending = update; // Update the childLanes even though we're most likely already rendering + // this fiber. This is for backwards compatibility in the case where you + // update a different component during render phase than the one that is + // currently renderings (a pattern that is accompanied by a warning). - if (!element._owner) { - 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." - ); + return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); + } else { + return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); } } - } + function entangleTransitions(root, fiber, lane) { + var updateQueue = fiber.updateQueue; - return mixedRef; -} + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return; + } -function throwOnInvalidObjectType(returnFiber, newChild) { - // $FlowFixMe[method-unbinding] - var childString = Object.prototype.toString.call(newChild); - 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." - ); -} - -function warnOnFunctionType(returnFiber) { - { - var componentName = getComponentNameFromFiber(returnFiber) || "Component"; - - if (ownerHasFunctionTypeWarning[componentName]) { - return; - } + var sharedQueue = updateQueue.shared; - ownerHasFunctionTypeWarning[componentName] = true; + if (isTransitionLane(lane)) { + var queueLanes = sharedQueue.lanes; // If any entangled lanes are no longer pending on the root, then they must + // have finished. We can remove them from the shared queue, which represents + // a superset of the actually pending lanes. In some cases we may entangle + // more than we need to, but that's OK. In fact it's worse if we *don't* + // entangle when we should. - error( - "Functions are not valid as a React child. This may happen if " + - "you return a Component instead of from render. " + - "Or maybe you meant to call this function rather than return it." - ); - } -} + queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. -function resolveLazy(lazyType) { - var payload = lazyType._payload; - var init = lazyType._init; - return init(payload); -} // This wrapper function exists because I expect to clone the code in each path -// to be able to optimize each path individually by branching early. This needs -// a compiler or we can do it manually. Helpers that don't need this branching -// live outside of this function. + var newQueueLanes = mergeLanes(queueLanes, lane); + sharedQueue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if + // the lane finished since the last time we entangled it. So we need to + // entangle it again, just to be sure. -function createChildReconciler(shouldTrackSideEffects) { - function deleteChild(returnFiber, childToDelete) { - if (!shouldTrackSideEffects) { - // Noop. - return; + markRootEntangled(root, newQueueLanes); + } } + function enqueueCapturedUpdate(workInProgress, capturedUpdate) { + // Captured updates are updates that are thrown by a child during the render + // phase. They should be discarded if the render is aborted. Therefore, + // we should only put them on the work-in-progress queue, not the current one. + var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone. - var deletions = returnFiber.deletions; + var current = workInProgress.alternate; - if (deletions === null) { - returnFiber.deletions = [childToDelete]; - returnFiber.flags |= ChildDeletion; - } else { - deletions.push(childToDelete); - } - } + if (current !== null) { + var currentQueue = current.updateQueue; + + if (queue === currentQueue) { + // The work-in-progress queue is the same as current. This happens when + // we bail out on a parent fiber that then captures an error thrown by + // a child. Since we want to append the update only to the work-in + // -progress queue, we need to clone the updates. We usually clone during + // processUpdateQueue, but that didn't happen in this case because we + // skipped over the parent when we bailed out. + var newFirst = null; + var newLast = null; + var firstBaseUpdate = queue.firstBaseUpdate; + + if (firstBaseUpdate !== null) { + // Loop through the updates and clone them. + var update = firstBaseUpdate; - function deleteRemainingChildren(returnFiber, currentFirstChild) { - if (!shouldTrackSideEffects) { - // Noop. - return null; - } // TODO: For the shouldClone case, this could be micro-optimized a bit by - // assuming that after the first child we've already added everything. + do { + var clone = { + lane: update.lane, + tag: update.tag, + payload: update.payload, + // When this update is rebased, we should not fire its + // callback again. + callback: null, + next: null + }; + + if (newLast === null) { + newFirst = newLast = clone; + } else { + newLast.next = clone; + newLast = clone; + } // $FlowFixMe[incompatible-type] we bail out when we get a null - var childToDelete = currentFirstChild; + update = update.next; + } while (update !== null); // Append the captured update the end of the cloned list. - while (childToDelete !== null) { - deleteChild(returnFiber, childToDelete); - childToDelete = childToDelete.sibling; - } + if (newLast === null) { + newFirst = newLast = capturedUpdate; + } else { + newLast.next = capturedUpdate; + newLast = capturedUpdate; + } + } else { + // There are no base updates. + newFirst = newLast = capturedUpdate; + } - return null; - } + queue = { + baseState: currentQueue.baseState, + firstBaseUpdate: newFirst, + lastBaseUpdate: newLast, + shared: currentQueue.shared, + callbacks: currentQueue.callbacks + }; + workInProgress.updateQueue = queue; + return; + } + } // Append the update to the end of the list. - function mapRemainingChildren(returnFiber, currentFirstChild) { - // Add the remaining children to a temporary map so that we can find them by - // keys quickly. Implicit (null) keys get added to this set with their index - // instead. - var existingChildren = new Map(); - var existingChild = currentFirstChild; + var lastBaseUpdate = queue.lastBaseUpdate; - while (existingChild !== null) { - if (existingChild.key !== null) { - existingChildren.set(existingChild.key, existingChild); + if (lastBaseUpdate === null) { + queue.firstBaseUpdate = capturedUpdate; } else { - existingChildren.set(existingChild.index, existingChild); + lastBaseUpdate.next = capturedUpdate; } - existingChild = existingChild.sibling; + queue.lastBaseUpdate = capturedUpdate; } - return existingChildren; - } + function getStateFromUpdate( + workInProgress, + queue, + update, + prevState, + nextProps, + instance + ) { + switch (update.tag) { + case ReplaceState: { + var payload = update.payload; + + if (typeof payload === "function") { + // Updater function + { + enterDisallowedContextReadInDEV(); + } - function useFiber(fiber, pendingProps) { - // We currently set sibling to null and index to 0 here because it is easy - // to forget to do before returning it. E.g. for the single child case. - var clone = createWorkInProgress(fiber, pendingProps); - clone.index = 0; - clone.sibling = null; - return clone; - } + var nextState = payload.call(instance, prevState, nextProps); - function placeChild(newFiber, lastPlacedIndex, newIndex) { - newFiber.index = newIndex; + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); - if (!shouldTrackSideEffects) { - // During hydration, the useId algorithm needs to know which fibers are - // part of a list of children (arrays, iterators). - newFiber.flags |= Forked; - return lastPlacedIndex; - } + try { + payload.call(instance, prevState, nextProps); + } finally { + setIsStrictModeForDevtools(false); + } + } - var current = newFiber.alternate; + exitDisallowedContextReadInDEV(); + } - if (current !== null) { - var oldIndex = current.index; + return nextState; + } // State object - if (oldIndex < lastPlacedIndex) { - // This is a move. - newFiber.flags |= Placement | PlacementDEV; - return lastPlacedIndex; - } else { - // This item can stay in place. - return oldIndex; - } - } else { - // This is an insertion. - newFiber.flags |= Placement | PlacementDEV; - return lastPlacedIndex; - } - } + return payload; + } - function placeSingleChild(newFiber) { - // This is simpler for the single child case. We only need to do a - // placement for inserting new children. - if (shouldTrackSideEffects && newFiber.alternate === null) { - newFiber.flags |= Placement | PlacementDEV; - } + case CaptureUpdate: { + workInProgress.flags = + (workInProgress.flags & ~ShouldCapture) | DidCapture; + } + // Intentional fallthrough - return newFiber; - } + case UpdateState: { + var _payload = update.payload; + var partialState; - function updateTextNode(returnFiber, current, textContent, lanes) { - if (current === null || current.tag !== HostText) { - // Insert - var created = createFiberFromText(textContent, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, textContent); - existing.return = returnFiber; - return existing; - } - } + if (typeof _payload === "function") { + // Updater function + { + enterDisallowedContextReadInDEV(); + } - function updateElement(returnFiber, current, element, lanes) { - var elementType = element.type; + partialState = _payload.call(instance, prevState, nextProps); - if (elementType === REACT_FRAGMENT_TYPE) { - return updateFragment( - returnFiber, - current, - element.props.children, - lanes, - element.key - ); - } + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); - if (current !== null) { - if ( - current.elementType === elementType || // Keep this check inline so it only runs on the false path: - isCompatibleFamilyForHotReloading(current, element) || // Lazy types should reconcile their resolved type. - // We need to do this after the Hot Reloading check above, - // because hot reloading has different semantics than prod because - // it doesn't resuspend. So we can't let the call below suspend. - (typeof elementType === "object" && - elementType !== null && - elementType.$$typeof === REACT_LAZY_TYPE && - resolveLazy(elementType) === current.type) - ) { - // Move based on index - var existing = useFiber(current, element.props); - existing.ref = coerceRef(returnFiber, current, element); - existing.return = returnFiber; + try { + _payload.call(instance, prevState, nextProps); + } finally { + setIsStrictModeForDevtools(false); + } + } - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; + exitDisallowedContextReadInDEV(); + } + } else { + // Partial state object + partialState = _payload; + } + + if (partialState === null || partialState === undefined) { + // Null and undefined are treated as no-ops. + return prevState; + } // Merge the partial state and the previous state. + + return assign({}, prevState, partialState); } - return existing; + case ForceUpdate: { + hasForceUpdate = true; + return prevState; + } } - } // Insert - var created = createFiberFromElement(element, returnFiber.mode, lanes); - created.ref = coerceRef(returnFiber, current, element); - created.return = returnFiber; - return created; - } - - function updatePortal(returnFiber, current, portal, lanes) { - if ( - current === null || - current.tag !== HostPortal || - current.stateNode.containerInfo !== portal.containerInfo || - current.stateNode.implementation !== portal.implementation - ) { - // Insert - var created = createFiberFromPortal(portal, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, portal.children || []); - existing.return = returnFiber; - return existing; - } - } - - function updateFragment(returnFiber, current, fragment, lanes, key) { - if (current === null || current.tag !== Fragment) { - // Insert - var created = createFiberFromFragment( - fragment, - returnFiber.mode, - lanes, - key - ); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, fragment); - existing.return = returnFiber; - return existing; + return prevState; } - } - function createChild(returnFiber, newChild, lanes) { - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys. If the previous node is implicitly keyed - // we can continue to replace it without aborting even if it is not a text - // node. - var created = createFiberFromText("" + newChild, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } - - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - var _created = createFiberFromElement( - newChild, - returnFiber.mode, - lanes - ); + function processUpdateQueue(workInProgress, props, instance, renderLanes) { + // This is always non-null on a ClassComponent or HostRoot + var queue = workInProgress.updateQueue; + hasForceUpdate = false; - _created.ref = coerceRef(returnFiber, null, newChild); - _created.return = returnFiber; - return _created; - } + { + currentlyProcessingQueue = queue.shared; + } - case REACT_PORTAL_TYPE: { - var _created2 = createFiberFromPortal( - newChild, - returnFiber.mode, - lanes - ); + var firstBaseUpdate = queue.firstBaseUpdate; + var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. - _created2.return = returnFiber; - return _created2; + var pendingQueue = queue.shared.pending; + + if (pendingQueue !== null) { + queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first + // and last so that it's non-circular. + + var lastPendingUpdate = pendingQueue; + var firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = null; // Append pending updates to base queue + + if (lastBaseUpdate === null) { + firstBaseUpdate = firstPendingUpdate; + } else { + lastBaseUpdate.next = firstPendingUpdate; } - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return createChild(returnFiber, init(payload), lanes); + lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then + // we need to transfer the updates to that queue, too. Because the base + // queue is a singly-linked list with no cycles, we can append to both + // lists and take advantage of structural sharing. + // TODO: Pass `current` as argument + + var current = workInProgress.alternate; + + if (current !== null) { + // This is always non-null on a ClassComponent or HostRoot + var currentQueue = current.updateQueue; + var currentLastBaseUpdate = currentQueue.lastBaseUpdate; + + if (currentLastBaseUpdate !== lastBaseUpdate) { + if (currentLastBaseUpdate === null) { + currentQueue.firstBaseUpdate = firstPendingUpdate; + } else { + currentLastBaseUpdate.next = firstPendingUpdate; + } + + currentQueue.lastBaseUpdate = lastPendingUpdate; + } } - } + } // These values may change as we process the queue. - if (isArray(newChild) || getIteratorFn(newChild)) { - var _created3 = createFiberFromFragment( - newChild, - returnFiber.mode, - lanes, - null - ); + if (firstBaseUpdate !== null) { + // Iterate through the list of updates to compute the result. + var newState = queue.baseState; // TODO: Don't need to accumulate this. Instead, we can remove renderLanes + // from the original lanes. + + var newLanes = NoLanes; + var newBaseState = null; + var newFirstBaseUpdate = null; + var newLastBaseUpdate = null; + var update = firstBaseUpdate; - _created3.return = returnFiber; - return _created3; - } // Usable node types - // - // Unwrap the inner value and recursively call this function again. + do { + // An extra OffscreenLane bit is added to updates that were made to + // a hidden tree, so that we can distinguish them from updates that were + // already there when the tree was hidden. + var updateLane = removeLanes(update.lane, OffscreenLane); + var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then + // it's not a "base" update and we should disregard the extra base lanes + // that were added to renderLanes when we entered the Offscreen tree. + + var shouldSkipUpdate = isHiddenUpdate + ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) + : !isSubsetOfLanes(renderLanes, updateLane); + + if (shouldSkipUpdate) { + // Priority is insufficient. Skip this update. If this is the first + // skipped update, the previous update/state is the new base + // update/state. + var clone = { + lane: updateLane, + tag: update.tag, + payload: update.payload, + callback: update.callback, + next: null + }; - if (typeof newChild.then === "function") { - var thenable = newChild; - return createChild(returnFiber, unwrapThenable(thenable), lanes); - } + if (newLastBaseUpdate === null) { + newFirstBaseUpdate = newLastBaseUpdate = clone; + newBaseState = newState; + } else { + newLastBaseUpdate = newLastBaseUpdate.next = clone; + } // Update the remaining priority in the queue. - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return createChild( - returnFiber, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes - ); - } + newLanes = mergeLanes(newLanes, updateLane); + } else { + // This update does have sufficient priority. + if (newLastBaseUpdate !== null) { + var _clone = { + // This update is going to be committed so we never want uncommit + // it. Using NoLane works because 0 is a subset of all bitmasks, so + // this will never be skipped by the check above. + lane: NoLane, + tag: update.tag, + payload: update.payload, + // When this update is rebased, we should not fire its + // callback again. + callback: null, + next: null + }; + newLastBaseUpdate = newLastBaseUpdate.next = _clone; + } // Process this update. + + newState = getStateFromUpdate( + workInProgress, + queue, + update, + newState, + props, + instance + ); + var callback = update.callback; - throwOnInvalidObjectType(returnFiber, newChild); - } + if (callback !== null) { + workInProgress.flags |= Callback; - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } - } + if (isHiddenUpdate) { + workInProgress.flags |= Visibility; + } - return null; - } + var callbacks = queue.callbacks; - function updateSlot(returnFiber, oldFiber, newChild, lanes) { - // Update the fiber if the keys match, otherwise return null. - var key = oldFiber !== null ? oldFiber.key : null; + if (callbacks === null) { + queue.callbacks = [callback]; + } else { + callbacks.push(callback); + } + } + } // $FlowFixMe[incompatible-type] we bail out when we get a null - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys. If the previous node is implicitly keyed - // we can continue to replace it without aborting even if it is not a text - // node. - if (key !== null) { - return null; - } + update = update.next; - return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); - } + if (update === null) { + pendingQueue = queue.shared.pending; - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - if (newChild.key === key) { - return updateElement(returnFiber, oldFiber, newChild, lanes); - } else { - return null; + if (pendingQueue === null) { + break; + } else { + // An update was scheduled from inside a reducer. Add the new + // pending updates to the end of the list and keep processing. + var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we + // unravel them when transferring them to the base queue. + + var _firstPendingUpdate = _lastPendingUpdate.next; + _lastPendingUpdate.next = null; + update = _firstPendingUpdate; + queue.lastBaseUpdate = _lastPendingUpdate; + queue.shared.pending = null; + } } - } + } while (true); - case REACT_PORTAL_TYPE: { - if (newChild.key === key) { - return updatePortal(returnFiber, oldFiber, newChild, lanes); - } else { - return null; - } + if (newLastBaseUpdate === null) { + newBaseState = newState; } - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return updateSlot(returnFiber, oldFiber, init(payload), lanes); - } - } + queue.baseState = newBaseState; + queue.firstBaseUpdate = newFirstBaseUpdate; + queue.lastBaseUpdate = newLastBaseUpdate; - if (isArray(newChild) || getIteratorFn(newChild)) { - if (key !== null) { - return null; - } + if (firstBaseUpdate === null) { + // `queue.lanes` is used for entangling transitions. We can set it back to + // zero once the queue is empty. + queue.shared.lanes = NoLanes; + } // Set the remaining expiration time to be whatever is remaining in the queue. + // This should be fine because the only two other things that contribute to + // expiration time are props and context. We're already in the middle of the + // begin phase by the time we start processing the queue, so we've already + // dealt with the props. Context in components that specify + // shouldComponentUpdate is tricky; but we'll have to account for + // that regardless. - return updateFragment(returnFiber, oldFiber, newChild, lanes, null); - } // Usable node types - // - // Unwrap the inner value and recursively call this function again. + markSkippedUpdateLanes(newLanes); + workInProgress.lanes = newLanes; + workInProgress.memoizedState = newState; + } - if (typeof newChild.then === "function") { - var thenable = newChild; - return updateSlot( - returnFiber, - oldFiber, - unwrapThenable(thenable), - lanes - ); + { + currentlyProcessingQueue = null; } + } - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return updateSlot( - returnFiber, - oldFiber, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes + function callCallback(callback, context) { + if (typeof callback !== "function") { + throw new Error( + "Invalid argument passed as callback. Expected a function. Instead " + + ("received: " + callback) ); } - throwOnInvalidObjectType(returnFiber, newChild); + callback.call(context); } - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } + function resetHasForceUpdateBeforeProcessing() { + hasForceUpdate = false; } + function checkHasForceUpdateAfterProcessing() { + return hasForceUpdate; + } + function deferHiddenCallbacks(updateQueue) { + // When an update finishes on a hidden component, its callback should not + // be fired until/unless the component is made visible again. Stash the + // callback on the shared queue object so it can be fired later. + var newHiddenCallbacks = updateQueue.callbacks; - return null; - } + if (newHiddenCallbacks !== null) { + var existingHiddenCallbacks = updateQueue.shared.hiddenCallbacks; - function updateFromMap( - existingChildren, - returnFiber, - newIdx, - newChild, - lanes - ) { - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys, so we neither have to check the old nor - // new node for the key. If both are text nodes, they match. - var matchedFiber = existingChildren.get(newIdx) || null; - return updateTextNode(returnFiber, matchedFiber, "" + newChild, lanes); + if (existingHiddenCallbacks === null) { + updateQueue.shared.hiddenCallbacks = newHiddenCallbacks; + } else { + updateQueue.shared.hiddenCallbacks = + existingHiddenCallbacks.concat(newHiddenCallbacks); + } + } } + function commitHiddenCallbacks(updateQueue, context) { + // This component is switching from hidden -> visible. Commit any callbacks + // that were previously deferred. + var hiddenCallbacks = updateQueue.shared.hiddenCallbacks; - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - var _matchedFiber = - existingChildren.get( - newChild.key === null ? newIdx : newChild.key - ) || null; + if (hiddenCallbacks !== null) { + updateQueue.shared.hiddenCallbacks = null; - return updateElement(returnFiber, _matchedFiber, newChild, lanes); + for (var i = 0; i < hiddenCallbacks.length; i++) { + var callback = hiddenCallbacks[i]; + callCallback(callback, context); } + } + } + function commitCallbacks(updateQueue, context) { + var callbacks = updateQueue.callbacks; - case REACT_PORTAL_TYPE: { - var _matchedFiber2 = - existingChildren.get( - newChild.key === null ? newIdx : newChild.key - ) || null; + if (callbacks !== null) { + updateQueue.callbacks = null; - return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); + for (var i = 0; i < callbacks.length; i++) { + var callback = callbacks[i]; + callCallback(callback, context); } - - case REACT_LAZY_TYPE: - var payload = newChild._payload; - var init = newChild._init; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - init(payload), - lanes - ); } + } - if (isArray(newChild) || getIteratorFn(newChild)) { - var _matchedFiber3 = existingChildren.get(newIdx) || null; - - return updateFragment( - returnFiber, - _matchedFiber3, - newChild, - lanes, - null - ); - } // Usable node types - // - // Unwrap the inner value and recursively call this function again. + /** + * Performs equality by iterating through keys on an object and returning false + * when any key has values which are not strictly equal between the arguments. + * Returns true when the values of all keys are strictly equal. + */ - if (typeof newChild.then === "function") { - var thenable = newChild; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - unwrapThenable(thenable), - lanes - ); + function shallowEqual(objA, objB) { + if (objectIs(objA, objB)) { + return true; } if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + typeof objA !== "object" || + objA === null || + typeof objB !== "object" || + objB === null ) { - var context = newChild; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes - ); + return false; } - throwOnInvalidObjectType(returnFiber, newChild); - } + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } - } + if (keysA.length !== keysB.length) { + return false; + } // Test for A's keys different from B. - return null; - } - /** - * Warns if there is a duplicate or missing key - */ + for (var i = 0; i < keysA.length; i++) { + var currentKey = keysA[i]; - function warnOnInvalidKey(child, knownKeys, returnFiber) { - { - if (typeof child !== "object" || child === null) { - return knownKeys; + if ( + !hasOwnProperty.call(objB, currentKey) || // $FlowFixMe[incompatible-use] lost refinement of `objB` + !objectIs(objA[currentKey], objB[currentKey]) + ) { + return false; + } } - switch (child.$$typeof) { - case REACT_ELEMENT_TYPE: - case REACT_PORTAL_TYPE: - warnForMissingKey(child, returnFiber); - var key = child.key; + return true; + } - if (typeof key !== "string") { - break; - } + function describeFiber(fiber) { + switch (fiber.tag) { + case HostHoistable: + case HostSingleton: + case HostComponent: + return describeBuiltInComponentFrame(fiber.type); - if (knownKeys === null) { - knownKeys = new Set(); - knownKeys.add(key); - break; - } + case LazyComponent: + return describeBuiltInComponentFrame("Lazy"); - if (!knownKeys.has(key)) { - knownKeys.add(key); - break; - } + case SuspenseComponent: + return describeBuiltInComponentFrame("Suspense"); - 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 - ); + case SuspenseListComponent: + return describeBuiltInComponentFrame("SuspenseList"); - break; + case FunctionComponent: + case IndeterminateComponent: + case SimpleMemoComponent: + return describeFunctionComponentFrame(fiber.type); - case REACT_LAZY_TYPE: - var payload = child._payload; - var init = child._init; - warnOnInvalidKey(init(payload), knownKeys, returnFiber); - break; - } - } + case ForwardRef: + return describeFunctionComponentFrame(fiber.type.render); - return knownKeys; - } - - function reconcileChildrenArray( - returnFiber, - currentFirstChild, - newChildren, - lanes - ) { - // This algorithm can't optimize by searching from both ends since we - // don't have backpointers on fibers. I'm trying to see how far we can get - // with that model. If it ends up not being worth the tradeoffs, we can - // add it later. - // Even with a two ended optimization, we'd want to optimize for the case - // where there are few changes and brute force the comparison instead of - // going for the Map. It'd like to explore hitting that path first in - // forward-only mode and only go for the Map once we notice that we need - // lots of look ahead. This doesn't handle reversal as well as two ended - // search but that's unusual. Besides, for the two ended optimization to - // work on Iterables, we'd need to copy the whole set. - // In this first iteration, we'll just live with hitting the bad case - // (adding everything to a Map) in for every insert/move. - // If you change this code, also update reconcileChildrenIterator() which - // uses the same algorithm. - { - // First, validate keys. - var knownKeys = null; + case ClassComponent: + return describeClassComponentFrame(fiber.type); - for (var i = 0; i < newChildren.length; i++) { - var child = newChildren[i]; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + default: + return ""; } } - var resultingFirstChild = null; - var previousNewFiber = null; - var oldFiber = currentFirstChild; - var lastPlacedIndex = 0; - var newIdx = 0; - var nextOldFiber = null; - - for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { - if (oldFiber.index > newIdx) { - nextOldFiber = oldFiber; - oldFiber = null; - } else { - nextOldFiber = oldFiber.sibling; - } + function getStackByFiberInDevAndProd(workInProgress) { + try { + var info = ""; + var node = workInProgress; - var newFiber = updateSlot( - returnFiber, - oldFiber, - newChildren[newIdx], - lanes - ); + do { + info += describeFiber(node); // $FlowFixMe[incompatible-type] we bail out when we get a null - if (newFiber === null) { - // TODO: This breaks on empty slots like null children. That's - // unfortunate because it triggers the slow path all the time. We need - // a better way to communicate whether this was a miss or null, - // boolean, undefined, etc. - if (oldFiber === null) { - oldFiber = nextOldFiber; - } + node = node.return; + } while (node); - break; + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; } + } - if (shouldTrackSideEffects) { - if (oldFiber && newFiber.alternate === null) { - // We matched the slot, but we didn't reuse the existing fiber, so we - // need to delete the existing child. - deleteChild(returnFiber, oldFiber); + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + var current = null; + var isRendering = false; + function getCurrentFiberOwnerNameInDevOrNull() { + { + if (current === null) { + return null; } - } - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + var owner = current._debugOwner; - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = newFiber; - } else { - // TODO: Defer siblings if we're not at the right index for this slot. - // I.e. if we had null values before, then we want to defer this - // for each null value. However, we also don't want to call updateSlot - // with the previous one. - previousNewFiber.sibling = newFiber; + if (owner !== null && typeof owner !== "undefined") { + return getComponentNameFromFiber(owner); + } } - previousNewFiber = newFiber; - oldFiber = nextOldFiber; + return null; } - if (newIdx === newChildren.length) { - // We've reached the end of the new children. We can delete the rest. - deleteRemainingChildren(returnFiber, oldFiber); + function getCurrentFiberStackInDev() { + { + if (current === null) { + return ""; + } // Safe because if current fiber exists, we are reconciling, + // and it is guaranteed to be the work-in-progress version. - return resultingFirstChild; + return getStackByFiberInDevAndProd(current); + } } - if (oldFiber === null) { - // If we don't have any more existing children we can choose a fast path - // since the rest will all be insertions. - for (; newIdx < newChildren.length; newIdx++) { - var _newFiber = createChild(returnFiber, newChildren[newIdx], lanes); - - if (_newFiber === null) { - continue; - } - - lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); - - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = _newFiber; - } else { - previousNewFiber.sibling = _newFiber; - } - - previousNewFiber = _newFiber; + function resetCurrentFiber() { + { + ReactDebugCurrentFrame.getCurrentStack = null; + current = null; + isRendering = false; } + } + function setCurrentFiber(fiber) { + { + ReactDebugCurrentFrame.getCurrentStack = + fiber === null ? null : getCurrentFiberStackInDev; + current = fiber; + isRendering = false; + } + } + function getCurrentFiber() { + { + return current; + } + } + function setIsRendering(rendering) { + { + isRendering = rendering; + } + } - return resultingFirstChild; - } // Add all children to a key map for quick lookups. - - var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + var ReactStrictModeWarnings = { + recordUnsafeLifecycleWarnings: function (fiber, instance) {}, + flushPendingUnsafeLifecycleWarnings: function () {}, + recordLegacyContextWarning: function (fiber, instance) {}, + flushLegacyContextWarning: function () {}, + discardPendingWarnings: function () {} + }; - for (; newIdx < newChildren.length; newIdx++) { - var _newFiber2 = updateFromMap( - existingChildren, - returnFiber, - newIdx, - newChildren[newIdx], - lanes - ); + { + var findStrictRoot = function (fiber) { + var maybeStrictRoot = null; + var node = fiber; - if (_newFiber2 !== null) { - if (shouldTrackSideEffects) { - if (_newFiber2.alternate !== null) { - // The new fiber is a work in progress, but if there exists a - // current, that means that we reused the fiber. We need to delete - // it from the child list so that we don't add it to the deletion - // list. - existingChildren.delete( - _newFiber2.key === null ? newIdx : _newFiber2.key - ); + while (node !== null) { + if (node.mode & StrictLegacyMode) { + maybeStrictRoot = node; } - } - lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); - - if (previousNewFiber === null) { - resultingFirstChild = _newFiber2; - } else { - previousNewFiber.sibling = _newFiber2; + node = node.return; } - previousNewFiber = _newFiber2; - } - } - - if (shouldTrackSideEffects) { - // Any existing children that weren't consumed above were deleted. We need - // to add them to the deletion list. - existingChildren.forEach(function (child) { - return deleteChild(returnFiber, child); - }); - } + return maybeStrictRoot; + }; - return resultingFirstChild; - } + var setToSortedString = function (set) { + var array = []; + set.forEach(function (value) { + array.push(value); + }); + return array.sort().join(", "); + }; - function reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChildrenIterable, - lanes - ) { - // This is the same implementation as reconcileChildrenArray(), - // but using the iterator instead. - var iteratorFn = getIteratorFn(newChildrenIterable); + var pendingComponentWillMountWarnings = []; + var pendingUNSAFE_ComponentWillMountWarnings = []; + var pendingComponentWillReceivePropsWarnings = []; + var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + var pendingComponentWillUpdateWarnings = []; + var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. - if (typeof iteratorFn !== "function") { - throw new Error( - "An object is not an iterable. This error is likely caused by a bug in " + - "React. Please file an issue." - ); - } + var didWarnAboutUnsafeLifecycles = new Set(); - { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if ( - typeof Symbol === "function" && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === "Generator" + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function ( + fiber, + instance ) { - if (!didWarnAboutGenerators) { - 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." - ); + // Dedupe strategy: Warn once per component. + if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { + return; } - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - if (newChildrenIterable.entries === iteratorFn) { - if (!didWarnAboutMaps) { - error( - "Using Maps as children is not supported. " + - "Use an array of keyed ReactElements instead." - ); + if ( + typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + pendingComponentWillMountWarnings.push(fiber); } - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillMount === "function" + ) { + pendingUNSAFE_ComponentWillMountWarnings.push(fiber); + } - var _newChildren = iteratorFn.call(newChildrenIterable); + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== + true + ) { + pendingComponentWillReceivePropsWarnings.push(fiber); + } - if (_newChildren) { - var knownKeys = null; + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); + } - var _step = _newChildren.next(); + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + pendingComponentWillUpdateWarnings.push(fiber); + } - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillUpdate === "function" + ) { + pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); } - } - } + }; - var newChildren = iteratorFn.call(newChildrenIterable); + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = + function () { + // We do an initial pass to gather component names + var componentWillMountUniqueNames = new Set(); - if (newChildren == null) { - throw new Error("An iterable object provided no iterator."); - } + if (pendingComponentWillMountWarnings.length > 0) { + pendingComponentWillMountWarnings.forEach(function (fiber) { + componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillMountWarnings = []; + } - var resultingFirstChild = null; - var previousNewFiber = null; - var oldFiber = currentFirstChild; - var lastPlacedIndex = 0; - var newIdx = 0; - var nextOldFiber = null; - var step = newChildren.next(); + var UNSAFE_componentWillMountUniqueNames = new Set(); - for ( - ; - oldFiber !== null && !step.done; - newIdx++, step = newChildren.next() - ) { - if (oldFiber.index > newIdx) { - nextOldFiber = oldFiber; - oldFiber = null; - } else { - nextOldFiber = oldFiber.sibling; - } + if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { + pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) { + UNSAFE_componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillMountWarnings = []; + } - var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); + var componentWillReceivePropsUniqueNames = new Set(); - if (newFiber === null) { - // TODO: This breaks on empty slots like null children. That's - // unfortunate because it triggers the slow path all the time. We need - // a better way to communicate whether this was a miss or null, - // boolean, undefined, etc. - if (oldFiber === null) { - oldFiber = nextOldFiber; - } + if (pendingComponentWillReceivePropsWarnings.length > 0) { + pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { + componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillReceivePropsWarnings = []; + } - break; - } + var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); - if (shouldTrackSideEffects) { - if (oldFiber && newFiber.alternate === null) { - // We matched the slot, but we didn't reuse the existing fiber, so we - // need to delete the existing child. - deleteChild(returnFiber, oldFiber); - } - } + if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach( + function (fiber) { + UNSAFE_componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + } + ); + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + } - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + var componentWillUpdateUniqueNames = new Set(); - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = newFiber; - } else { - // TODO: Defer siblings if we're not at the right index for this slot. - // I.e. if we had null values before, then we want to defer this - // for each null value. However, we also don't want to call updateSlot - // with the previous one. - previousNewFiber.sibling = newFiber; - } + if (pendingComponentWillUpdateWarnings.length > 0) { + pendingComponentWillUpdateWarnings.forEach(function (fiber) { + componentWillUpdateUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillUpdateWarnings = []; + } - previousNewFiber = newFiber; - oldFiber = nextOldFiber; - } + var UNSAFE_componentWillUpdateUniqueNames = new Set(); - if (step.done) { - // We've reached the end of the new children. We can delete the rest. - deleteRemainingChildren(returnFiber, oldFiber); + if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { + pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function (fiber) { + UNSAFE_componentWillUpdateUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillUpdateWarnings = []; + } // Finally, we flush all the warnings + // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' - return resultingFirstChild; - } + if (UNSAFE_componentWillMountUniqueNames.size > 0) { + var sortedNames = setToSortedString( + UNSAFE_componentWillMountUniqueNames + ); - if (oldFiber === null) { - // If we don't have any more existing children we can choose a fast path - // since the rest will all be insertions. - for (; !step.done; newIdx++, step = newChildren.next()) { - var _newFiber3 = createChild(returnFiber, step.value, lanes); + 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 + ); + } - if (_newFiber3 === null) { - continue; - } + if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames = setToSortedString( + UNSAFE_componentWillReceivePropsUniqueNames + ); - lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); + 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 + ); + } - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = _newFiber3; - } else { - previousNewFiber.sibling = _newFiber3; - } + if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { + var _sortedNames2 = setToSortedString( + UNSAFE_componentWillUpdateUniqueNames + ); - previousNewFiber = _newFiber3; - } + 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 + ); + } - return resultingFirstChild; - } // Add all children to a key map for quick lookups. + if (componentWillMountUniqueNames.size > 0) { + var _sortedNames3 = setToSortedString( + componentWillMountUniqueNames + ); - var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + 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 + ); + } - for (; !step.done; newIdx++, step = newChildren.next()) { - var _newFiber4 = updateFromMap( - existingChildren, - returnFiber, - newIdx, - step.value, - lanes - ); + if (componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames4 = setToSortedString( + componentWillReceivePropsUniqueNames + ); - if (_newFiber4 !== null) { - if (shouldTrackSideEffects) { - if (_newFiber4.alternate !== null) { - // The new fiber is a work in progress, but if there exists a - // current, that means that we reused the fiber. We need to delete - // it from the child list so that we don't add it to the deletion - // list. - existingChildren.delete( - _newFiber4.key === null ? newIdx : _newFiber4.key + 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 ); } - } - lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); + if (componentWillUpdateUniqueNames.size > 0) { + var _sortedNames5 = setToSortedString( + componentWillUpdateUniqueNames + ); - if (previousNewFiber === null) { - resultingFirstChild = _newFiber4; - } else { - previousNewFiber.sibling = _newFiber4; - } + 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 + ); + } + }; - previousNewFiber = _newFiber4; - } - } + var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. - if (shouldTrackSideEffects) { - // Any existing children that weren't consumed above were deleted. We need - // to add them to the deletion list. - existingChildren.forEach(function (child) { - return deleteChild(returnFiber, child); - }); - } + var didWarnAboutLegacyContext = new Set(); - return resultingFirstChild; - } - - function reconcileSingleTextNode( - returnFiber, - currentFirstChild, - textContent, - lanes - ) { - // There's no need to check for keys on text nodes since we don't have a - // way to define them. - if (currentFirstChild !== null && currentFirstChild.tag === HostText) { - // We already have an existing node so let's just update it and delete - // the rest. - deleteRemainingChildren(returnFiber, currentFirstChild.sibling); - var existing = useFiber(currentFirstChild, textContent); - existing.return = returnFiber; - return existing; - } // The existing first child is not a text node so we need to create one - // and delete the existing ones. - - deleteRemainingChildren(returnFiber, currentFirstChild); - var created = createFiberFromText(textContent, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } - - function reconcileSingleElement( - returnFiber, - currentFirstChild, - element, - lanes - ) { - var key = element.key; - var child = currentFirstChild; - - while (child !== null) { - // TODO: If key === null and child.key === null, then this only applies to - // the first item in the list. - if (child.key === key) { - var elementType = element.type; + ReactStrictModeWarnings.recordLegacyContextWarning = function ( + fiber, + instance + ) { + var strictRoot = findStrictRoot(fiber); - if (elementType === REACT_FRAGMENT_TYPE) { - if (child.tag === Fragment) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, element.props.children); - existing.return = returnFiber; + if (strictRoot === null) { + 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." + ); - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; - } + return; + } // Dedup strategy: Warn once per component. - return existing; - } - } else { - if ( - child.elementType === elementType || // Keep this check inline so it only runs on the false path: - isCompatibleFamilyForHotReloading(child, element) || // Lazy types should reconcile their resolved type. - // We need to do this after the Hot Reloading check above, - // because hot reloading has different semantics than prod because - // it doesn't resuspend. So we can't let the call below suspend. - (typeof elementType === "object" && - elementType !== null && - elementType.$$typeof === REACT_LAZY_TYPE && - resolveLazy(elementType) === child.type) - ) { - deleteRemainingChildren(returnFiber, child.sibling); + if (didWarnAboutLegacyContext.has(fiber.type)) { + return; + } - var _existing = useFiber(child, element.props); + var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); - _existing.ref = coerceRef(returnFiber, child, element); - _existing.return = returnFiber; + if ( + fiber.type.contextTypes != null || + fiber.type.childContextTypes != null || + (instance !== null && typeof instance.getChildContext === "function") + ) { + if (warningsForRoot === undefined) { + warningsForRoot = []; + pendingLegacyContextWarning.set(strictRoot, warningsForRoot); + } - { - _existing._debugSource = element._source; - _existing._debugOwner = element._owner; - } + warningsForRoot.push(fiber); + } + }; - return _existing; + ReactStrictModeWarnings.flushLegacyContextWarning = function () { + pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) { + if (fiberArray.length === 0) { + return; } - } // Didn't match. - deleteRemainingChildren(returnFiber, child); - break; - } else { - deleteChild(returnFiber, child); - } + var firstFiber = fiberArray[0]; + var uniqueNames = new Set(); + fiberArray.forEach(function (fiber) { + uniqueNames.add(getComponentNameFromFiber(fiber) || "Component"); + didWarnAboutLegacyContext.add(fiber.type); + }); + var sortedNames = setToSortedString(uniqueNames); - child = child.sibling; - } + try { + setCurrentFiber(firstFiber); - if (element.type === REACT_FRAGMENT_TYPE) { - var created = createFiberFromFragment( - element.props.children, - returnFiber.mode, - lanes, - element.key - ); - created.return = returnFiber; - return created; - } else { - var _created4 = createFiberFromElement(element, returnFiber.mode, lanes); - - _created4.ref = coerceRef(returnFiber, currentFirstChild, element); - _created4.return = returnFiber; - return _created4; - } - } - - function reconcileSinglePortal( - returnFiber, - currentFirstChild, - portal, - lanes - ) { - var key = portal.key; - var child = currentFirstChild; - - while (child !== null) { - // TODO: If key === null and child.key === null, then this only applies to - // the first item in the list. - if (child.key === key) { - if ( - child.tag === HostPortal && - child.stateNode.containerInfo === portal.containerInfo && - child.stateNode.implementation === portal.implementation - ) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, portal.children || []); - existing.return = returnFiber; - return existing; - } else { - deleteRemainingChildren(returnFiber, child); - break; - } - } else { - deleteChild(returnFiber, child); - } - - child = child.sibling; - } - - var created = createFiberFromPortal(portal, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } // This API will tag the children with the side-effect of the reconciliation - // itself. They will be added to the side-effect list as we pass through the - // children and the parent. - - function reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - newChild, - lanes - ) { - // This function is not recursive. - // If the top level item is an array, we treat it as a set of children, - // not as a fragment. Nested arrays on the other hand will be treated as - // fragment nodes. Recursion happens at the normal flow. - // Handle top level unkeyed fragments as if they were arrays. - // This leads to an ambiguity between <>{[...]} and <>.... - // We treat the ambiguous cases above the same. - // TODO: Let's use recursion like we do for Usable nodes? - var isUnkeyedTopLevelFragment = - typeof newChild === "object" && - newChild !== null && - newChild.type === REACT_FRAGMENT_TYPE && - newChild.key === null; - - if (isUnkeyedTopLevelFragment) { - newChild = newChild.props.children; - } // Handle object types - - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: - return placeSingleChild( - reconcileSingleElement( - returnFiber, - currentFirstChild, - newChild, - lanes - ) - ); + 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 + ); + } finally { + resetCurrentFiber(); + } + }); + }; - case REACT_PORTAL_TYPE: - return placeSingleChild( - reconcileSinglePortal( - returnFiber, - currentFirstChild, - newChild, - lanes - ) - ); + ReactStrictModeWarnings.discardPendingWarnings = function () { + pendingComponentWillMountWarnings = []; + pendingUNSAFE_ComponentWillMountWarnings = []; + pendingComponentWillReceivePropsWarnings = []; + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + pendingComponentWillUpdateWarnings = []; + pendingUNSAFE_ComponentWillUpdateWarnings = []; + pendingLegacyContextWarning = new Map(); + }; + } - case REACT_LAZY_TYPE: - var payload = newChild._payload; - var init = newChild._init; // TODO: This function is supposed to be non-recursive. + /* + * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol + * and Temporal.* types. See https://github.com/facebook/react/pull/22064. + * + * The functions in this module will throw an easier-to-understand, + * easier-to-debug exception with a clear errors message message explaining the + * problem. (Instead of a confusing exception thrown inside the implementation + * of the `value` object). + */ + // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. + function typeName(value) { + { + // toStringTag is needed for namespaced types like Temporal.Instant + var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; + var type = + (hasToStringTag && value[Symbol.toStringTag]) || + value.constructor.name || + "Object"; // $FlowFixMe[incompatible-return] - return reconcileChildFibers( - returnFiber, - currentFirstChild, - init(payload), - lanes - ); + return type; } + } // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - if (isArray(newChild)) { - return reconcileChildrenArray( - returnFiber, - currentFirstChild, - newChild, - lanes - ); + function willCoercionThrow(value) { + { + try { + testStringCoercion(value); + return false; + } catch (e) { + return true; + } } + } - if (getIteratorFn(newChild)) { - return reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChild, - lanes - ); - } // Usables are a valid React node type. When React encounters a Usable in - // a child position, it unwraps it using the same algorithm as `use`. For - // example, for promises, React will throw an exception to unwind the - // stack, then replay the component once the promise resolves. + function testStringCoercion(value) { + // If you ended up here by following an exception call stack, here's what's + // happened: you supplied an object or symbol value to React (as a prop, key, + // DOM attribute, CSS property, string ref, etc.) and when React tried to + // coerce it to a string using `'' + value`, an exception was thrown. // - // A difference from `use` is that React will keep unwrapping the value - // until it reaches a non-Usable type. + // The most common types that will cause this exception are `Symbol` instances + // and Temporal objects like `Temporal.Instant`. But any object that has a + // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this + // exception. (Library authors do this to prevent users from using built-in + // numeric operators like `+` or comparison operators like `>=` because custom + // methods are needed to perform accurate arithmetic or comparison.) // - // e.g. Usable>> should resolve to T + // To fix the problem, coerce this object or symbol value to a string before + // passing it to React. The most reliable way is usually `String(value)`. // - // The structure is a bit unfortunate. Ideally, we shouldn't need to - // replay the entire begin phase of the parent fiber in order to reconcile - // the children again. This would require a somewhat significant refactor, - // because reconcilation happens deep within the begin phase, and - // depending on the type of work, not always at the end. We should - // consider as an future improvement. - - if (typeof newChild.then === "function") { - var thenable = newChild; - return reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - unwrapThenable(thenable), - lanes - ); - } + // To find which value is throwing, check the browser or debugger console. + // Before this exception was thrown, there should be `console.error` output + // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the + // problem and how that type was used: key, atrribute, input value prop, etc. + // In most cases, this console output also shows the component and its + // ancestor components where the exception happened. + // + // eslint-disable-next-line react-internal/safe-string-coercion + return "" + value; + } + function checkPropStringCoercion(value, propName) { + { + if (willCoercionThrow(value)) { + error( + "The provided `%s` prop is an unsupported type %s." + + " This value must be coerced to a string before using it here.", + propName, + typeName(value) + ); - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes - ); + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + } } - - throwOnInvalidObjectType(returnFiber, newChild); } - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - return placeSingleChild( - reconcileSingleTextNode( - returnFiber, - currentFirstChild, - "" + newChild, - lanes - ) - ); - } + var ReactCurrentActQueue$3 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we + // detect this is caught by userspace, we'll log a warning in development. - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } - } // Remaining cases are all treated as empty. - - return deleteRemainingChildren(returnFiber, currentFirstChild); - } - - function reconcileChildFibers( - returnFiber, - currentFirstChild, - newChild, - lanes - ) { - // This indirection only exists so we can reset `thenableState` at the end. - // It should get inlined by Closure. - thenableIndexCounter$1 = 0; - var firstChildFiber = reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - newChild, - lanes + var SuspenseException = new Error( + "Suspense Exception: This is not a real error! It's an implementation " + + "detail of `use` to interrupt the current render. You must either " + + "rethrow it immediately, or move the `use` call outside of the " + + "`try/catch` block. Capturing without rethrowing will lead to " + + "unexpected behavior.\n\n" + + "To handle async errors, wrap your component in an error boundary, or " + + "call the promise's `.catch` method and pass the result to `use`" ); - thenableState$1 = null; // Don't bother to reset `thenableIndexCounter` to 0 because it always gets - // set at the beginning. - - return firstChildFiber; - } - - return reconcileChildFibers; -} + var SuspenseyCommitException = new Error( + "Suspense Exception: This is not a real error, and should not leak into " + + "userspace. If you're seeing this, it's likely a bug in React." + ); // This is a noop thenable that we use to trigger a fallback in throwException. + // TODO: It would be better to refactor throwException into multiple functions + // so we can trigger a fallback directly without having to check the type. But + // for now this will do. + + var noopSuspenseyCommitThenable = { + then: function () { + { + error( + "Internal React error: A listener was unexpectedly attached to a " + + '"noop" thenable. This is a bug in React. Please file an issue.' + ); + } + } + }; + function createThenableState() { + // The ThenableState is created the first time a component suspends. If it + // suspends again, we'll reuse the same state. + return []; + } + function isThenableResolved(thenable) { + var status = thenable.status; + return status === "fulfilled" || status === "rejected"; + } -var reconcileChildFibers = createChildReconciler(true); -var mountChildFibers = createChildReconciler(false); -function resetChildReconcilerOnUnwind() { - // On unwind, clear any pending thenables that were used. - thenableState$1 = null; - thenableIndexCounter$1 = 0; -} -function cloneChildFibers(current, workInProgress) { - if (current !== null && workInProgress.child !== current.child) { - throw new Error("Resuming work not yet implemented."); - } - - if (workInProgress.child === null) { - return; - } - - var currentChild = workInProgress.child; - var newChild = createWorkInProgress(currentChild, currentChild.pendingProps); - workInProgress.child = newChild; - newChild.return = workInProgress; - - while (currentChild.sibling !== null) { - currentChild = currentChild.sibling; - newChild = newChild.sibling = createWorkInProgress( - currentChild, - currentChild.pendingProps - ); - newChild.return = workInProgress; - } + function noop() {} - newChild.sibling = null; -} // Reset a workInProgress child set to prepare it for a second pass. + function trackUsedThenable(thenableState, thenable, index) { + if (ReactCurrentActQueue$3.current !== null) { + ReactCurrentActQueue$3.didUsePromise = true; + } -function resetChildFibers(workInProgress, lanes) { - var child = workInProgress.child; + var previous = thenableState[index]; - while (child !== null) { - resetWorkInProgress(child, lanes); - child = child.sibling; - } -} + if (previous === undefined) { + thenableState.push(thenable); + } else { + if (previous !== thenable) { + // Reuse the previous thenable, and drop the new one. We can assume + // they represent the same value, because components are idempotent. + // Avoid an unhandled rejection errors for the Promises that we'll + // intentionally ignore. + thenable.then(noop, noop); + thenable = previous; + } + } // We use an expando to track the status and result of a thenable so that we + // can synchronously unwrap the value. Think of this as an extension of the + // Promise API, or a custom interface that is a superset of Thenable. + // + // If the thenable doesn't have a status, set it to "pending" and attach + // a listener that will update its status and result when it resolves. -// TODO: This isn't being used yet, but it's intended to replace the -// InvisibleParentContext that is currently managed by SuspenseContext. - -var currentTreeHiddenStackCursor = createCursor(null); -var prevEntangledRenderLanesCursor = createCursor(NoLanes); -function pushHiddenContext(fiber, context) { - var prevEntangledRenderLanes = getEntangledRenderLanes(); - push(prevEntangledRenderLanesCursor, prevEntangledRenderLanes, fiber); - push(currentTreeHiddenStackCursor, context, fiber); // When rendering a subtree that's currently hidden, we must include all - // lanes that would have rendered if the hidden subtree hadn't been deferred. - // That is, in order to reveal content from hidden -> visible, we must commit - // all the updates that we skipped when we originally hid the tree. - - setEntangledRenderLanes( - mergeLanes(prevEntangledRenderLanes, context.baseLanes) - ); -} -function reuseHiddenContextOnStack(fiber) { - // This subtree is not currently hidden, so we don't need to add any lanes - // to the render lanes. But we still need to push something to avoid a - // context mismatch. Reuse the existing context on the stack. - push(prevEntangledRenderLanesCursor, getEntangledRenderLanes(), fiber); - push( - currentTreeHiddenStackCursor, - currentTreeHiddenStackCursor.current, - fiber - ); -} -function popHiddenContext(fiber) { - // Restore the previous render lanes from the stack - setEntangledRenderLanes(prevEntangledRenderLanesCursor.current); - pop(currentTreeHiddenStackCursor, fiber); - pop(prevEntangledRenderLanesCursor, fiber); -} -function isCurrentTreeHidden() { - return currentTreeHiddenStackCursor.current !== null; -} + switch (thenable.status) { + case "fulfilled": { + var fulfilledValue = thenable.value; + return fulfilledValue; + } -// suspends, i.e. it's the nearest `catch` block on the stack. - -var suspenseHandlerStackCursor = createCursor(null); // Represents the outermost boundary that is not visible in the current tree. -// Everything above this is the "shell". When this is null, it means we're -// rendering in the shell of the app. If it's non-null, it means we're rendering -// deeper than the shell, inside a new tree that wasn't already visible. -// -// The main way we use this concept is to determine whether showing a fallback -// would result in a desirable or undesirable loading state. Activing a fallback -// in the shell is considered an undersirable loading state, because it would -// mean hiding visible (albeit stale) content in the current tree — we prefer to -// show the stale content, rather than switch to a fallback. But showing a -// fallback in a new tree is fine, because there's no stale content to -// prefer instead. - -var shellBoundary = null; -function getShellBoundary() { - return shellBoundary; -} -function pushPrimaryTreeSuspenseHandler(handler) { - // TODO: Pass as argument - var current = handler.alternate; - var props = handler.pendingProps; // Shallow Suspense context fields, like ForceSuspenseFallback, should only be - // propagated a single level. For example, when ForceSuspenseFallback is set, - // it should only force the nearest Suspense boundary into fallback mode. - - pushSuspenseListContext( - handler, - setDefaultShallowSuspenseListContext(suspenseStackCursor.current) - ); // Experimental feature: Some Suspense boundaries are marked as having an - // undesirable fallback state. These have special behavior where we only - // activate the fallback if there's no other boundary on the stack that we can - // use instead. - - if ( - props.unstable_avoidThisFallback === true && // If an avoided boundary is already visible, it behaves identically to - // a regular Suspense boundary. - (current === null || isCurrentTreeHidden()) - ) { - if (shellBoundary === null) { - // We're rendering in the shell. There's no parent Suspense boundary that - // can provide a desirable fallback state. We'll use this boundary. - push(suspenseHandlerStackCursor, handler, handler); // However, because this is not a desirable fallback, the children are - // still considered part of the shell. So we intentionally don't assign - // to `shellBoundary`. - } else { - // There's already a parent Suspense boundary that can provide a desirable - // fallback state. Prefer that one. - var handlerOnStack = suspenseHandlerStackCursor.current; - push(suspenseHandlerStackCursor, handlerOnStack, handler); - } + case "rejected": { + var rejectedError = thenable.reason; + checkIfUseWrappedInAsyncCatch(rejectedError); + throw rejectedError; + } + + default: { + if (typeof thenable.status === "string") { + // Only instrument the thenable if the status if not defined. If + // it's defined, but an unknown value, assume it's been instrumented by + // some custom userspace implementation. We treat it as "pending". + // Attach a dummy listener, to ensure that any lazy initialization can + // happen. Flight lazily parses JSON when the value is actually awaited. + thenable.then(noop, noop); + } else { + // This is an uncached thenable that we haven't seen before. + // Detect infinite ping loops caused by uncached promises. + var root = getWorkInProgressRoot(); + + if (root !== null && root.shellSuspendCounter > 100) { + // This root has suspended repeatedly in the shell without making any + // progress (i.e. committing something). This is highly suggestive of + // an infinite ping loop, often caused by an accidental Async Client + // Component. + // + // During a transition, we can suspend the work loop until the promise + // to resolve, but this is a sync render, so that's not an option. We + // also can't show a fallback, because none was provided. So our last + // resort is to throw an error. + // + // TODO: Remove this error in a future release. Other ways of handling + // this case include forcing a concurrent render, or putting the whole + // root into offscreen mode. + throw new Error( + "async/await is not yet supported in Client Components, only " + + "Server Components. This error is often caused by accidentally " + + "adding `'use client'` to a module that was originally written " + + "for the server." + ); + } - return; - } // TODO: If the parent Suspense handler already suspended, there's no reason - // to push a nested Suspense handler, because it will get replaced by the - // outer fallback, anyway. Consider this as a future optimization. + var pendingThenable = thenable; + pendingThenable.status = "pending"; + pendingThenable.then( + function (fulfilledValue) { + if (thenable.status === "pending") { + var fulfilledThenable = thenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = fulfilledValue; + } + }, + function (error) { + if (thenable.status === "pending") { + var rejectedThenable = thenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; + } + } + ); // Check one more time in case the thenable resolved synchronously. - push(suspenseHandlerStackCursor, handler, handler); + switch (thenable.status) { + case "fulfilled": { + var fulfilledThenable = thenable; + return fulfilledThenable.value; + } - if (shellBoundary === null) { - if (current === null || isCurrentTreeHidden()) { - // This boundary is not visible in the current UI. - shellBoundary = handler; - } else { - var prevState = current.memoizedState; + case "rejected": { + var rejectedThenable = thenable; + var _rejectedError = rejectedThenable.reason; + checkIfUseWrappedInAsyncCatch(_rejectedError); + throw _rejectedError; + } + } + } // Suspend. + // + // Throwing here is an implementation detail that allows us to unwind the + // call stack. But we shouldn't allow it to leak into userspace. Throw an + // opaque placeholder value instead of the actual thenable. If it doesn't + // get captured by the work loop, log a warning, because that means + // something in userspace must have caught it. + + suspendedThenable = thenable; - if (prevState !== null) { - // This boundary is showing a fallback in the current UI. - shellBoundary = handler; + { + needsToResetSuspendedThenableDEV = true; + } + + throw SuspenseException; + } } } - } -} -function pushFallbackTreeSuspenseHandler(fiber) { - // We're about to render the fallback. If something in the fallback suspends, - // it's akin to throwing inside of a `catch` block. This boundary should not - // capture. Reuse the existing handler on the stack. - reuseSuspenseHandlerOnStack(fiber); -} -function pushOffscreenSuspenseHandler(fiber) { - if (fiber.tag === OffscreenComponent) { - // A SuspenseList context is only pushed here to avoid a push/pop mismatch. - // Reuse the current value on the stack. - // TODO: We can avoid needing to push here by by forking popSuspenseHandler - // into separate functions for Suspense and Offscreen. - pushSuspenseListContext(fiber, suspenseStackCursor.current); - push(suspenseHandlerStackCursor, fiber, fiber); - - if (shellBoundary !== null); - else { - var current = fiber.alternate; + // passed to the rest of the Suspense implementation — which, for historical + // reasons, expects to receive a thenable. - if (current !== null) { - var prevState = current.memoizedState; + var suspendedThenable = null; + var needsToResetSuspendedThenableDEV = false; + function getSuspendedThenable() { + // This is called right after `use` suspends by throwing an exception. `use` + // throws an opaque value instead of the thenable itself so that it can't be + // caught in userspace. Then the work loop accesses the actual thenable using + // this function. + if (suspendedThenable === null) { + throw new Error( + "Expected a suspended thenable. This is a bug in React. Please file " + + "an issue." + ); + } - if (prevState !== null) { - // This is the first boundary in the stack that's already showing - // a fallback. So everything outside is considered the shell. - shellBoundary = fiber; + var thenable = suspendedThenable; + suspendedThenable = null; + + { + needsToResetSuspendedThenableDEV = false; + } + + return thenable; + } + function checkIfUseWrappedInTryCatch() { + { + // This was set right before SuspenseException was thrown, and it should + // have been cleared when the exception was handled. If it wasn't, + // it must have been caught by userspace. + if (needsToResetSuspendedThenableDEV) { + needsToResetSuspendedThenableDEV = false; + return true; } } + + return false; + } + function checkIfUseWrappedInAsyncCatch(rejectedReason) { + // This check runs in prod, too, because it prevents a more confusing + // downstream error, where SuspenseException is caught by a promise and + // thrown asynchronously. + // TODO: Another way to prevent SuspenseException from leaking into an async + // execution context is to check the dispatcher every time `use` is called, + // or some equivalent. That might be preferable for other reasons, too, since + // it matches how we prevent similar mistakes for other hooks. + if (rejectedReason === SuspenseException) { + throw new Error( + "Hooks are not supported inside an async component. This " + + "error is often caused by accidentally adding `'use client'` " + + "to a module that was originally written for the server." + ); + } } - } else { - // This is a LegacyHidden component. - reuseSuspenseHandlerOnStack(fiber); - } -} -function reuseSuspenseHandlerOnStack(fiber) { - pushSuspenseListContext(fiber, suspenseStackCursor.current); - push(suspenseHandlerStackCursor, getSuspenseHandler(), fiber); -} -function getSuspenseHandler() { - return suspenseHandlerStackCursor.current; -} -function popSuspenseHandler(fiber) { - pop(suspenseHandlerStackCursor, fiber); - - if (shellBoundary === fiber) { - // Popping back into the shell. - shellBoundary = null; - } - - popSuspenseListContext(fiber); -} // SuspenseList context -// TODO: Move to a separate module? We may change the SuspenseList -// implementation to hide/show in the commit phase, anyway. - -var DefaultSuspenseContext = 0; -var SubtreeSuspenseContextMask = 1; // ForceSuspenseFallback can be used by SuspenseList to force newly added -// items into their fallback state during one of the render passes. - -var ForceSuspenseFallback = 2; -var suspenseStackCursor = createCursor(DefaultSuspenseContext); -function hasSuspenseListContext(parentContext, flag) { - return (parentContext & flag) !== 0; -} -function setDefaultShallowSuspenseListContext(parentContext) { - return parentContext & SubtreeSuspenseContextMask; -} -function setShallowSuspenseListContext(parentContext, shallowContext) { - return (parentContext & SubtreeSuspenseContextMask) | shallowContext; -} -function pushSuspenseListContext(fiber, newContext) { - push(suspenseStackCursor, newContext, fiber); -} -function popSuspenseListContext(fiber) { - pop(suspenseStackCursor, fiber); -} -// A non-null SuspenseState means that it is blocked for one reason or another. -// - A non-null dehydrated field means it's blocked pending hydration. -// - A non-null dehydrated field can use isSuspenseInstancePending or -// isSuspenseInstanceFallback to query the reason for being dehydrated. -// - A null dehydrated field means it's blocked by something suspending and -// we're currently showing a fallback instead. + var thenableState$1 = null; + var thenableIndexCounter$1 = 0; + var didWarnAboutMaps; + var didWarnAboutGenerators; + var didWarnAboutStringRefs; + var ownerHasKeyUseWarning; + var ownerHasFunctionTypeWarning; -function findFirstSuspended(row) { - var node = row; + var warnForMissingKey = function (child, returnFiber) {}; + + { + didWarnAboutMaps = false; + didWarnAboutGenerators = false; + didWarnAboutStringRefs = {}; + /** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ + + ownerHasKeyUseWarning = {}; + ownerHasFunctionTypeWarning = {}; + + warnForMissingKey = function (child, returnFiber) { + if (child === null || typeof child !== "object") { + return; + } - while (node !== null) { - if (node.tag === SuspenseComponent) { - var state = node.memoizedState; + if (!child._store || child._store.validated || child.key != null) { + return; + } - if (state !== null) { - var dehydrated = state.dehydrated; + if (typeof child._store !== "object") { + 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." + ); + } // $FlowFixMe[cannot-write] unable to narrow type from mixed to writable object - if ( - dehydrated === null || - isSuspenseInstancePending() || - isSuspenseInstanceFallback() - ) { - return node; + child._store.validated = true; + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; + + if (ownerHasKeyUseWarning[componentName]) { + return; } - } - } else if ( - node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't - // keep track of whether it suspended or not. - node.memoizedProps.revealOrder !== undefined - ) { - var didSuspend = (node.flags & DidCapture) !== NoFlags$1; - if (didSuspend) { - return node; - } - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; + ownerHasKeyUseWarning[componentName] = true; + + error( + "Each child in a list should have a unique " + + '"key" prop. See https://reactjs.org/link/warning-keys for ' + + "more information." + ); + }; } - if (node === row) { - return null; + function isReactClass(type) { + return type.prototype && type.prototype.isReactComponent; } - while (node.sibling === null) { - if (node.return === null || node.return === row) { - return null; + function unwrapThenable(thenable) { + var index = thenableIndexCounter$1; + thenableIndexCounter$1 += 1; + + if (thenableState$1 === null) { + thenableState$1 = createThenableState(); } - node = node.return; + return trackUsedThenable(thenableState$1, thenable, index); } - node.sibling.return = node.return; - node = node.sibling; - } + function coerceRef(returnFiber, current, element) { + var mixedRef = element.ref; - return null; -} + if ( + mixedRef !== null && + typeof mixedRef !== "function" && + typeof mixedRef !== "object" + ) { + { + if ( + // We warn in ReactElement.js if owner and self are equal for string refs + // because these cannot be automatically converted to an arrow function + // using a codemod. Therefore, we don't have to warn about string refs again. + !( + element._owner && + element._self && + element._owner.stateNode !== element._self + ) && // Will already throw with "Function components cannot have string refs" + !(element._owner && element._owner.tag !== ClassComponent) && // Will already warn with "Function components cannot be given refs" + !( + typeof element.type === "function" && !isReactClass(element.type) + ) && // Will already throw with "Element ref was specified as a string (someStringRef) but no owner was set" + element._owner + ) { + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; -var NoFlags = - /* */ - 0; // Represents whether effect should fire. - -var HasEffect = - /* */ - 1; // Represents the phase in which the effect (not the clean-up) fires. - -var Insertion = - /* */ - 2; -var Layout = - /* */ - 4; -var Passive = - /* */ - 8; - -var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // A linked list of all the roots with pending work. In an idiomatic app, -// there's only a single root, but we do support multi root apps, hence this -// extra complexity. But this module is optimized for the single root case. - -var firstScheduledRoot = null; -var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. - -var didScheduleMicrotask = false; // `act` "microtasks" are scheduled on the `act` queue instead of an actual -// microtask, so we have to dedupe those separately. This wouldn't be an issue -// if we required all `act` calls to be awaited, which we might in the future. - -var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. - -var mightHavePendingSyncWork = false; -var isFlushingWork = false; -var currentEventTransitionLane = NoLane; -function ensureRootIsScheduled(root) { - // This function is called whenever a root receives an update. It does two - // things 1) it ensures the root is in the root schedule, and 2) it ensures - // there's a pending microtask to process the root schedule. - // - // Most of the actual scheduling logic does not happen until - // `scheduleTaskForRootDuringMicrotask` runs. - // Add the root to the schedule - if (root === lastScheduledRoot || root.next !== null); - else { - if (lastScheduledRoot === null) { - firstScheduledRoot = lastScheduledRoot = root; - } else { - lastScheduledRoot.next = root; - lastScheduledRoot = root; - } - } // Any time a root received an update, we set this to true until the next time - // we process the schedule. If it's false, then we can quickly exit flushSync - // without consulting the schedule. - - mightHavePendingSyncWork = true; // At the end of the current event, go through each of the roots and ensure - // there's a task scheduled for each one at the correct priority. - - if (ReactCurrentActQueue$2.current !== null) { - // We're inside an `act` scope. - if (!didScheduleMicrotask_act) { - didScheduleMicrotask_act = true; - scheduleImmediateTask(processRootScheduleInMicrotask); - } - } else { - if (!didScheduleMicrotask) { - didScheduleMicrotask = true; - scheduleImmediateTask(processRootScheduleInMicrotask); - } - } - - if (!enableDeferRootSchedulingToMicrotask) { - // While this flag is disabled, we schedule the render task immediately - // instead of waiting a microtask. - // TODO: We need to land enableDeferRootSchedulingToMicrotask ASAP to - // unblock additional features we have planned. - scheduleTaskForRootDuringMicrotask(root, now$1()); - } - - if (ReactCurrentActQueue$2.isBatchingLegacy && root.tag === LegacyRoot) { - // Special `act` case: Record whenever a legacy update is scheduled. - ReactCurrentActQueue$2.didScheduleLegacyUpdate = true; - } -} -function flushSyncWorkOnAllRoots() { - // This is allowed to be called synchronously, but the caller should check - // the execution context first. - flushSyncWorkAcrossRoots_impl(false); -} -function flushSyncWorkOnLegacyRootsOnly() { - // This is allowed to be called synchronously, but the caller should check - // the execution context first. - flushSyncWorkAcrossRoots_impl(true); -} + if (!didWarnAboutStringRefs[componentName]) { + 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 + ); -function flushSyncWorkAcrossRoots_impl(onlyLegacy) { - if (isFlushingWork) { - // Prevent reentrancy. - // TODO: Is this overly defensive? The callers must check the execution - // context first regardless. - return; - } - - if (!mightHavePendingSyncWork) { - // Fast path. There's no sync work to do. - return; - } // There may or may not be synchronous work scheduled. Let's check. - - var didPerformSomeWork; - var errors = null; - isFlushingWork = true; - - do { - didPerformSomeWork = false; - var root = firstScheduledRoot; - - while (root !== null) { - if (onlyLegacy && root.tag !== LegacyRoot); - else { - var workInProgressRoot = getWorkInProgressRoot(); - var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); - var nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes - ); + didWarnAboutStringRefs[componentName] = true; + } + } + } - if (includesSyncLane(nextLanes)) { - // This root has pending sync work. Flush it now. - try { - didPerformSomeWork = true; - performSyncWorkOnRoot(root, nextLanes); - } catch (error) { - // Collect errors so we can rethrow them at the end - if (errors === null) { - errors = [error]; + if (element._owner) { + var owner = element._owner; + var inst; + + if (owner) { + var ownerFiber = owner; + + if (ownerFiber.tag !== ClassComponent) { + 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" + ); + } + + inst = ownerFiber.stateNode; + } + + if (!inst) { + throw new Error( + "Missing owner for string ref " + + mixedRef + + ". This error is likely caused by a " + + "bug in React. Please file an issue." + ); + } // Assigning this to a const so Flow knows it won't change in the closure + + var resolvedInst = inst; + + { + checkPropStringCoercion(mixedRef, "ref"); + } + + var stringRef = "" + mixedRef; // Check if previous string ref matches new string ref + + if ( + current !== null && + current.ref !== null && + typeof current.ref === "function" && + current.ref._stringRef === stringRef + ) { + return current.ref; + } + + var ref = function (value) { + var refs = resolvedInst.refs; + + if (value === null) { + delete refs[stringRef]; } else { - errors.push(error); + refs[stringRef] = value; } + }; + + ref._stringRef = stringRef; + return ref; + } else { + if (typeof mixedRef !== "string") { + throw new Error( + "Expected ref to be a function, a string, an object returned by React.createRef(), or null." + ); + } + + if (!element._owner) { + 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." + ); } } } - root = root.next; + return mixedRef; + } + + function throwOnInvalidObjectType(returnFiber, newChild) { + // $FlowFixMe[method-unbinding] + var childString = Object.prototype.toString.call(newChild); + 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." + ); } - } while (didPerformSomeWork); - isFlushingWork = false; // If any errors were thrown, rethrow them right before exiting. - // TODO: Consider returning these to the caller, to allow them to decide - // how/when to rethrow. + function warnOnFunctionType(returnFiber) { + { + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; - if (errors !== null) { - if (errors.length > 1) { - if (typeof AggregateError === "function") { - // eslint-disable-next-line no-undef - throw new AggregateError(errors); - } else { - for (var i = 1; i < errors.length; i++) { - scheduleImmediateTask(throwError.bind(null, errors[i])); + if (ownerHasFunctionTypeWarning[componentName]) { + return; } - var firstError = errors[0]; - throw firstError; + ownerHasFunctionTypeWarning[componentName] = true; + + error( + "Functions are not valid as a React child. This may happen if " + + "you return a Component instead of from render. " + + "Or maybe you meant to call this function rather than return it." + ); } - } else { - var error = errors[0]; - throw error; } - } -} - -function throwError(error) { - throw error; -} -function processRootScheduleInMicrotask() { - // This function is always called inside a microtask. It should never be - // called synchronously. - didScheduleMicrotask = false; + function resolveLazy(lazyType) { + var payload = lazyType._payload; + var init = lazyType._init; + return init(payload); + } // This wrapper function exists because I expect to clone the code in each path + // to be able to optimize each path individually by branching early. This needs + // a compiler or we can do it manually. Helpers that don't need this branching + // live outside of this function. - { - didScheduleMicrotask_act = false; - } // We'll recompute this as we iterate through all the roots and schedule them. + function createChildReconciler(shouldTrackSideEffects) { + function deleteChild(returnFiber, childToDelete) { + if (!shouldTrackSideEffects) { + // Noop. + return; + } - mightHavePendingSyncWork = false; - var currentTime = now$1(); - var prev = null; - var root = firstScheduledRoot; + var deletions = returnFiber.deletions; - while (root !== null) { - var next = root.next; + if (deletions === null) { + returnFiber.deletions = [childToDelete]; + returnFiber.flags |= ChildDeletion; + } else { + deletions.push(childToDelete); + } + } - if ( - currentEventTransitionLane !== NoLane && - shouldAttemptEagerTransition() - ) { - // A transition was scheduled during an event, but we're going to try to - // render it synchronously anyway. We do this during a popstate event to - // preserve the scroll position of the previous page. - upgradePendingLaneToSync(root, currentEventTransitionLane); - } + function deleteRemainingChildren(returnFiber, currentFirstChild) { + if (!shouldTrackSideEffects) { + // Noop. + return null; + } // TODO: For the shouldClone case, this could be micro-optimized a bit by + // assuming that after the first child we've already added everything. - var nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); + var childToDelete = currentFirstChild; - if (nextLanes === NoLane) { - // This root has no more pending work. Remove it from the schedule. To - // guard against subtle reentrancy bugs, this microtask is the only place - // we do this — you can add roots to the schedule whenever, but you can - // only remove them here. - // Null this out so we know it's been removed from the schedule. - root.next = null; + while (childToDelete !== null) { + deleteChild(returnFiber, childToDelete); + childToDelete = childToDelete.sibling; + } - if (prev === null) { - // This is the new head of the list - firstScheduledRoot = next; - } else { - prev.next = next; + return null; } - if (next === null) { - // This is the new tail of the list - lastScheduledRoot = prev; - } - } else { - // This root still has work. Keep it in the list. - prev = root; + function mapRemainingChildren(returnFiber, currentFirstChild) { + // Add the remaining children to a temporary map so that we can find them by + // keys quickly. Implicit (null) keys get added to this set with their index + // instead. + var existingChildren = new Map(); + var existingChild = currentFirstChild; - if (includesSyncLane(nextLanes)) { - mightHavePendingSyncWork = true; + while (existingChild !== null) { + if (existingChild.key !== null) { + existingChildren.set(existingChild.key, existingChild); + } else { + existingChildren.set(existingChild.index, existingChild); + } + + existingChild = existingChild.sibling; + } + + return existingChildren; } - } - root = next; - } + function useFiber(fiber, pendingProps) { + // We currently set sibling to null and index to 0 here because it is easy + // to forget to do before returning it. E.g. for the single child case. + var clone = createWorkInProgress(fiber, pendingProps); + clone.index = 0; + clone.sibling = null; + return clone; + } - currentEventTransitionLane = NoLane; // At the end of the microtask, flush any pending synchronous work. This has - // to come at the end, because it does actual rendering work that might throw. + function placeChild(newFiber, lastPlacedIndex, newIndex) { + newFiber.index = newIndex; - flushSyncWorkOnAllRoots(); -} + if (!shouldTrackSideEffects) { + // During hydration, the useId algorithm needs to know which fibers are + // part of a list of children (arrays, iterators). + newFiber.flags |= Forked; + return lastPlacedIndex; + } -function scheduleTaskForRootDuringMicrotask(root, currentTime) { - // This function is always called inside a microtask, or at the very end of a - // rendering task right before we yield to the main thread. It should never be - // called synchronously. - // - // TODO: Unless enableDeferRootSchedulingToMicrotask is off. We need to land - // that ASAP to unblock additional features we have planned. - // - // This function also never performs React work synchronously; it should - // only schedule work to be performed later, in a separate task or microtask. - // Check if any lanes are being starved by other work. If so, mark them as - // expired so we know to work on those next. - markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. - - var workInProgressRoot = getWorkInProgressRoot(); - var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); - var nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes - ); - var existingCallbackNode = root.callbackNode; - - if ( - // Check if there's nothing to work on - nextLanes === NoLanes || // If this root is currently suspended and waiting for data to resolve, don't - // schedule a task to render it. We'll either wait for a ping, or wait to - // receive an update. - // - // Suspended render phase - (root === workInProgressRoot && isWorkLoopSuspendedOnData()) || // Suspended commit phase - root.cancelPendingCommit !== null - ) { - // Fast path: There's nothing to work on. - if (existingCallbackNode !== null) { - cancelCallback(existingCallbackNode); - } - - root.callbackNode = null; - root.callbackPriority = NoLane; - return NoLane; - } // Schedule a new callback in the host environment. - - if (includesSyncLane(nextLanes)) { - // Synchronous work is always flushed at the end of the microtask, so we - // don't need to schedule an additional task. - if (existingCallbackNode !== null) { - cancelCallback(existingCallbackNode); - } - - root.callbackPriority = SyncLane; - root.callbackNode = null; - return SyncLane; - } else { - // We use the highest priority lane to represent the priority of the callback. - var existingCallbackPriority = root.callbackPriority; - var newCallbackPriority = getHighestPriorityLane(nextLanes); + var current = newFiber.alternate; - if ( - newCallbackPriority === existingCallbackPriority && // Special case related to `act`. If the currently scheduled task is a - // Scheduler task, rather than an `act` task, cancel it and re-schedule - // on the `act` queue. - !( - ReactCurrentActQueue$2.current !== null && - existingCallbackNode !== fakeActCallbackNode$1 - ) - ) { - // The priority hasn't changed. We can reuse the existing task. - return newCallbackPriority; - } else { - // Cancel the existing callback. We'll schedule a new one below. - cancelCallback(existingCallbackNode); - } + if (current !== null) { + var oldIndex = current.index; - var schedulerPriorityLevel; + if (oldIndex < lastPlacedIndex) { + // This is a move. + newFiber.flags |= Placement | PlacementDEV; + return lastPlacedIndex; + } else { + // This item can stay in place. + return oldIndex; + } + } else { + // This is an insertion. + newFiber.flags |= Placement | PlacementDEV; + return lastPlacedIndex; + } + } - switch (lanesToEventPriority(nextLanes)) { - case DiscreteEventPriority: - schedulerPriorityLevel = ImmediatePriority; - break; + function placeSingleChild(newFiber) { + // This is simpler for the single child case. We only need to do a + // placement for inserting new children. + if (shouldTrackSideEffects && newFiber.alternate === null) { + newFiber.flags |= Placement | PlacementDEV; + } - case ContinuousEventPriority: - schedulerPriorityLevel = UserBlockingPriority; - break; + return newFiber; + } - case DefaultEventPriority: - schedulerPriorityLevel = NormalPriority$1; - break; + function updateTextNode(returnFiber, current, textContent, lanes) { + if (current === null || current.tag !== HostText) { + // Insert + var created = createFiberFromText( + textContent, + returnFiber.mode, + lanes + ); + created.return = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, textContent); + existing.return = returnFiber; + return existing; + } + } - case IdleEventPriority: - schedulerPriorityLevel = IdlePriority; - break; + function updateElement(returnFiber, current, element, lanes) { + var elementType = element.type; - default: - schedulerPriorityLevel = NormalPriority$1; - break; - } + if (elementType === REACT_FRAGMENT_TYPE) { + return updateFragment( + returnFiber, + current, + element.props.children, + lanes, + element.key + ); + } - var newCallbackNode = scheduleCallback$2( - schedulerPriorityLevel, - performConcurrentWorkOnRoot.bind(null, root) - ); - root.callbackPriority = newCallbackPriority; - root.callbackNode = newCallbackNode; - return newCallbackPriority; - } -} + if (current !== null) { + if ( + current.elementType === elementType || // Keep this check inline so it only runs on the false path: + isCompatibleFamilyForHotReloading(current, element) || // Lazy types should reconcile their resolved type. + // We need to do this after the Hot Reloading check above, + // because hot reloading has different semantics than prod because + // it doesn't resuspend. So we can't let the call below suspend. + (typeof elementType === "object" && + elementType !== null && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === current.type) + ) { + // Move based on index + var existing = useFiber(current, element.props); + existing.ref = coerceRef(returnFiber, current, element); + existing.return = returnFiber; -function getContinuationForRoot(root, originalCallbackNode) { - // This is called at the end of `performConcurrentWorkOnRoot` to determine - // if we need to schedule a continuation task. - // - // Usually `scheduleTaskForRootDuringMicrotask` only runs inside a microtask; - // however, since most of the logic for determining if we need a continuation - // versus a new task is the same, we cheat a bit and call it here. This is - // only safe to do because we know we're at the end of the browser task. - // So although it's not an actual microtask, it might as well be. - scheduleTaskForRootDuringMicrotask(root, now$1()); - - if (root.callbackNode === originalCallbackNode) { - // The task node scheduled for this root is the same one that's - // currently executed. Need to return a continuation. - return performConcurrentWorkOnRoot.bind(null, root); - } - - return null; -} -var fakeActCallbackNode$1 = {}; - -function scheduleCallback$2(priorityLevel, callback) { - if (ReactCurrentActQueue$2.current !== null) { - // Special case: We're inside an `act` scope (a testing utility). - // Instead of scheduling work in the host environment, add it to a - // fake internal queue that's managed by the `act` implementation. - ReactCurrentActQueue$2.current.push(callback); - return fakeActCallbackNode$1; - } else { - return scheduleCallback$3(priorityLevel, callback); - } -} + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } -function cancelCallback(callbackNode) { - if (callbackNode === fakeActCallbackNode$1); - else if (callbackNode !== null) { - cancelCallback$1(callbackNode); - } -} + return existing; + } + } // Insert -function scheduleImmediateTask(cb) { - if (ReactCurrentActQueue$2.current !== null) { - // Special case: Inside an `act` scope, we push microtasks to the fake `act` - // callback queue. This is because we currently support calling `act` - // without awaiting the result. The plan is to deprecate that, and require - // that you always await the result so that the microtasks have a chance to - // run. But it hasn't happened yet. - ReactCurrentActQueue$2.current.push(function () { - cb(); - return null; - }); - } // TODO: Can we land supportsMicrotasks? Which environments don't support it? - // Alternatively, can we move this check to the host config? + var created = createFiberFromElement(element, returnFiber.mode, lanes); + created.ref = coerceRef(returnFiber, current, element); + created.return = returnFiber; + return created; + } - { - // If microtasks are not supported, use Scheduler. - scheduleCallback$3(ImmediatePriority, cb); - } -} + function updatePortal(returnFiber, current, portal, lanes) { + if ( + current === null || + current.tag !== HostPortal || + current.stateNode.containerInfo !== portal.containerInfo || + current.stateNode.implementation !== portal.implementation + ) { + // Insert + var created = createFiberFromPortal(portal, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, portal.children || []); + existing.return = returnFiber; + return existing; + } + } -function requestTransitionLane() { - // The algorithm for assigning an update to a lane should be stable for all - // updates at the same priority within the same event. To do this, the - // inputs to the algorithm must be the same. - // - // The trick we use is to cache the first of each of these inputs within an - // event. Then reset the cached values once we can be sure the event is - // over. Our heuristic for that is whenever we enter a concurrent work loop. - if (currentEventTransitionLane === NoLane) { - // All transitions within the same event are assigned the same lane. - currentEventTransitionLane = claimNextTransitionLane(); - } - - return currentEventTransitionLane; -} + function updateFragment(returnFiber, current, fragment, lanes, key) { + if (current === null || current.tag !== Fragment) { + // Insert + var created = createFiberFromFragment( + fragment, + returnFiber.mode, + lanes, + key + ); + created.return = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, fragment); + existing.return = returnFiber; + return existing; + } + } -// transition updates that occur while the async action is still in progress -// are treated as part of the action. -// -// The ideal behavior would be to treat each async function as an independent -// action. However, without a mechanism like AsyncContext, we can't tell which -// action an update corresponds to. So instead, we entangle them all into one. -// The listeners to notify once the entangled scope completes. - -var currentEntangledListeners = null; // The number of pending async actions in the entangled scope. - -var currentEntangledPendingCount = 0; // The transition lane shared by all updates in the entangled scope. - -var currentEntangledLane = NoLane; -function requestAsyncActionContext( - actionReturnValue, // If this is provided, this resulting thenable resolves to this value instead - // of the return value of the action. This is a perf trick to avoid composing - // an extra async function. - overrideReturnValue -) { - // This is an async action. - // - // Return a thenable that resolves once the action scope (i.e. the async - // function passed to startTransition) has finished running. - var thenable = actionReturnValue; - var entangledListeners; - - if (currentEntangledListeners === null) { - // There's no outer async action scope. Create a new one. - entangledListeners = currentEntangledListeners = []; - currentEntangledPendingCount = 0; - currentEntangledLane = requestTransitionLane(); - } else { - entangledListeners = currentEntangledListeners; - } - - currentEntangledPendingCount++; // Create a thenable that represents the result of this action, but doesn't - // resolve until the entire entangled scope has finished. - // - // Expressed using promises: - // const [thisResult] = await Promise.all([thisAction, entangledAction]); - // return thisResult; - - var resultThenable = createResultThenable(entangledListeners); - var resultStatus = "pending"; - var resultValue; - var rejectedReason; - thenable.then( - function (value) { - resultStatus = "fulfilled"; - resultValue = overrideReturnValue !== null ? overrideReturnValue : value; - pingEngtangledActionScope(); - }, - function (error) { - resultStatus = "rejected"; - rejectedReason = error; - pingEngtangledActionScope(); - } - ); // Attach a listener to fill in the result. - - entangledListeners.push(function () { - switch (resultStatus) { - case "fulfilled": { - var fulfilledThenable = resultThenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = resultValue; - break; - } - - case "rejected": { - var rejectedThenable = resultThenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = rejectedReason; - break; - } - - case "pending": - default: { - // The listener above should have been called first, so `resultStatus` - // should already be set to the correct value. - throw new Error( - "Thenable should have already resolved. This " + "is a bug in React." + function createChild(returnFiber, newChild, lanes) { + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + var created = createFiberFromText( + "" + newChild, + returnFiber.mode, + lanes + ); + created.return = returnFiber; + return created; + } + + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _created = createFiberFromElement( + newChild, + returnFiber.mode, + lanes + ); + + _created.ref = coerceRef(returnFiber, null, newChild); + _created.return = returnFiber; + return _created; + } + + case REACT_PORTAL_TYPE: { + var _created2 = createFiberFromPortal( + newChild, + returnFiber.mode, + lanes + ); + + _created2.return = returnFiber; + return _created2; + } + + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return createChild(returnFiber, init(payload), lanes); + } + } + + if (isArray(newChild) || getIteratorFn(newChild)) { + var _created3 = createFiberFromFragment( + newChild, + returnFiber.mode, + lanes, + null + ); + + _created3.return = returnFiber; + return _created3; + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return createChild(returnFiber, unwrapThenable(thenable), lanes); + } + + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return createChild( + returnFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } + + throwOnInvalidObjectType(returnFiber, newChild); + } + + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } + + return null; + } + + function updateSlot(returnFiber, oldFiber, newChild, lanes) { + // Update the fiber if the keys match, otherwise return null. + var key = oldFiber !== null ? oldFiber.key : null; + + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + if (key !== null) { + return null; + } + + return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); + } + + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + if (newChild.key === key) { + return updateElement(returnFiber, oldFiber, newChild, lanes); + } else { + return null; + } + } + + case REACT_PORTAL_TYPE: { + if (newChild.key === key) { + return updatePortal(returnFiber, oldFiber, newChild, lanes); + } else { + return null; + } + } + + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return updateSlot(returnFiber, oldFiber, init(payload), lanes); + } + } + + if (isArray(newChild) || getIteratorFn(newChild)) { + if (key !== null) { + return null; + } + + return updateFragment(returnFiber, oldFiber, newChild, lanes, null); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateSlot( + returnFiber, + oldFiber, + unwrapThenable(thenable), + lanes + ); + } + + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateSlot( + returnFiber, + oldFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } + + throwOnInvalidObjectType(returnFiber, newChild); + } + + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } + + return null; + } + + function updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChild, + lanes + ) { + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + // Text nodes don't have keys, so we neither have to check the old nor + // new node for the key. If both are text nodes, they match. + var matchedFiber = existingChildren.get(newIdx) || null; + return updateTextNode( + returnFiber, + matchedFiber, + "" + newChild, + lanes + ); + } + + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _matchedFiber = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; + + return updateElement(returnFiber, _matchedFiber, newChild, lanes); + } + + case REACT_PORTAL_TYPE: { + var _matchedFiber2 = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; + + return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); + } + + case REACT_LAZY_TYPE: + var payload = newChild._payload; + var init = newChild._init; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + init(payload), + lanes + ); + } + + if (isArray(newChild) || getIteratorFn(newChild)) { + var _matchedFiber3 = existingChildren.get(newIdx) || null; + + return updateFragment( + returnFiber, + _matchedFiber3, + newChild, + lanes, + null + ); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + unwrapThenable(thenable), + lanes + ); + } + + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } + + throwOnInvalidObjectType(returnFiber, newChild); + } + + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } + + return null; + } + /** + * Warns if there is a duplicate or missing key + */ + + function warnOnInvalidKey(child, knownKeys, returnFiber) { + { + if (typeof child !== "object" || child === null) { + return knownKeys; + } + + switch (child.$$typeof) { + case REACT_ELEMENT_TYPE: + case REACT_PORTAL_TYPE: + warnForMissingKey(child, returnFiber); + var key = child.key; + + if (typeof key !== "string") { + break; + } + + if (knownKeys === null) { + knownKeys = new Set(); + knownKeys.add(key); + break; + } + + if (!knownKeys.has(key)) { + knownKeys.add(key); + break; + } + + 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 + ); + + break; + + case REACT_LAZY_TYPE: + var payload = child._payload; + var init = child._init; + warnOnInvalidKey(init(payload), knownKeys, returnFiber); + break; + } + } + + return knownKeys; + } + + function reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChildren, + lanes + ) { + // This algorithm can't optimize by searching from both ends since we + // don't have backpointers on fibers. I'm trying to see how far we can get + // with that model. If it ends up not being worth the tradeoffs, we can + // add it later. + // Even with a two ended optimization, we'd want to optimize for the case + // where there are few changes and brute force the comparison instead of + // going for the Map. It'd like to explore hitting that path first in + // forward-only mode and only go for the Map once we notice that we need + // lots of look ahead. This doesn't handle reversal as well as two ended + // search but that's unusual. Besides, for the two ended optimization to + // work on Iterables, we'd need to copy the whole set. + // In this first iteration, we'll just live with hitting the bad case + // (adding everything to a Map) in for every insert/move. + // If you change this code, also update reconcileChildrenIterator() which + // uses the same algorithm. + { + // First, validate keys. + var knownKeys = null; + + for (var i = 0; i < newChildren.length; i++) { + var child = newChildren[i]; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + } + } + + var resultingFirstChild = null; + var previousNewFiber = null; + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; + + for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } + + var newFiber = updateSlot( + returnFiber, + oldFiber, + newChildren[newIdx], + lanes + ); + + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (oldFiber === null) { + oldFiber = nextOldFiber; + } + + break; + } + + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); + } + } + + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber; + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber; + } + + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } + + if (newIdx === newChildren.length) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); + + return resultingFirstChild; + } + + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber = createChild( + returnFiber, + newChildren[newIdx], + lanes + ); + + if (_newFiber === null) { + continue; + } + + lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber; + } else { + previousNewFiber.sibling = _newFiber; + } + + previousNewFiber = _newFiber; + } + + return resultingFirstChild; + } // Add all children to a key map for quick lookups. + + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber2 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChildren[newIdx], + lanes + ); + + if (_newFiber2 !== null) { + if (shouldTrackSideEffects) { + if (_newFiber2.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren.delete( + _newFiber2.key === null ? newIdx : _newFiber2.key + ); + } + } + + lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + resultingFirstChild = _newFiber2; + } else { + previousNewFiber.sibling = _newFiber2; + } + + previousNewFiber = _newFiber2; + } + } + + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function (child) { + return deleteChild(returnFiber, child); + }); + } + + return resultingFirstChild; + } + + function reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChildrenIterable, + lanes + ) { + // This is the same implementation as reconcileChildrenArray(), + // but using the iterator instead. + var iteratorFn = getIteratorFn(newChildrenIterable); + + if (typeof iteratorFn !== "function") { + throw new Error( + "An object is not an iterable. This error is likely caused by a bug in " + + "React. Please file an issue." + ); + } + + { + // We don't support rendering Generators because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + if ( + typeof Symbol === "function" && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag + newChildrenIterable[Symbol.toStringTag] === "Generator" + ) { + if (!didWarnAboutGenerators) { + 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." + ); + } + + didWarnAboutGenerators = true; + } // Warn about using Maps as children + + if (newChildrenIterable.entries === iteratorFn) { + if (!didWarnAboutMaps) { + error( + "Using Maps as children is not supported. " + + "Use an array of keyed ReactElements instead." + ); + } + + didWarnAboutMaps = true; + } // First, validate keys. + // We'll get a different iterator later for the main pass. + + var _newChildren = iteratorFn.call(newChildrenIterable); + + if (_newChildren) { + var knownKeys = null; + + var _step = _newChildren.next(); + + for (; !_step.done; _step = _newChildren.next()) { + var child = _step.value; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + } + } + } + + var newChildren = iteratorFn.call(newChildrenIterable); + + if (newChildren == null) { + throw new Error("An iterable object provided no iterator."); + } + + var resultingFirstChild = null; + var previousNewFiber = null; + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; + var step = newChildren.next(); + + for ( + ; + oldFiber !== null && !step.done; + newIdx++, step = newChildren.next() + ) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } + + var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); + + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (oldFiber === null) { + oldFiber = nextOldFiber; + } + + break; + } + + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); + } + } + + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber; + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber; + } + + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } + + if (step.done) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); + + return resultingFirstChild; + } + + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber3 = createChild(returnFiber, step.value, lanes); + + if (_newFiber3 === null) { + continue; + } + + lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber3; + } else { + previousNewFiber.sibling = _newFiber3; + } + + previousNewFiber = _newFiber3; + } + + return resultingFirstChild; + } // Add all children to a key map for quick lookups. + + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber4 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + step.value, + lanes + ); + + if (_newFiber4 !== null) { + if (shouldTrackSideEffects) { + if (_newFiber4.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren.delete( + _newFiber4.key === null ? newIdx : _newFiber4.key + ); + } + } + + lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + resultingFirstChild = _newFiber4; + } else { + previousNewFiber.sibling = _newFiber4; + } + + previousNewFiber = _newFiber4; + } + } + + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function (child) { + return deleteChild(returnFiber, child); + }); + } + + return resultingFirstChild; + } + + function reconcileSingleTextNode( + returnFiber, + currentFirstChild, + textContent, + lanes + ) { + // There's no need to check for keys on text nodes since we don't have a + // way to define them. + if (currentFirstChild !== null && currentFirstChild.tag === HostText) { + // We already have an existing node so let's just update it and delete + // the rest. + deleteRemainingChildren(returnFiber, currentFirstChild.sibling); + var existing = useFiber(currentFirstChild, textContent); + existing.return = returnFiber; + return existing; + } // The existing first child is not a text node so we need to create one + // and delete the existing ones. + + deleteRemainingChildren(returnFiber, currentFirstChild); + var created = createFiberFromText(textContent, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } + + function reconcileSingleElement( + returnFiber, + currentFirstChild, + element, + lanes + ) { + var key = element.key; + var child = currentFirstChild; + + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + var elementType = element.type; + + if (elementType === REACT_FRAGMENT_TYPE) { + if (child.tag === Fragment) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, element.props.children); + existing.return = returnFiber; + + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } + + return existing; + } + } else { + if ( + child.elementType === elementType || // Keep this check inline so it only runs on the false path: + isCompatibleFamilyForHotReloading(child, element) || // Lazy types should reconcile their resolved type. + // We need to do this after the Hot Reloading check above, + // because hot reloading has different semantics than prod because + // it doesn't resuspend. So we can't let the call below suspend. + (typeof elementType === "object" && + elementType !== null && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === child.type) + ) { + deleteRemainingChildren(returnFiber, child.sibling); + + var _existing = useFiber(child, element.props); + + _existing.ref = coerceRef(returnFiber, child, element); + _existing.return = returnFiber; + + { + _existing._debugSource = element._source; + _existing._debugOwner = element._owner; + } + + return _existing; + } + } // Didn't match. + + deleteRemainingChildren(returnFiber, child); + break; + } else { + deleteChild(returnFiber, child); + } + + child = child.sibling; + } + + if (element.type === REACT_FRAGMENT_TYPE) { + var created = createFiberFromFragment( + element.props.children, + returnFiber.mode, + lanes, + element.key + ); + created.return = returnFiber; + return created; + } else { + var _created4 = createFiberFromElement( + element, + returnFiber.mode, + lanes + ); + + _created4.ref = coerceRef(returnFiber, currentFirstChild, element); + _created4.return = returnFiber; + return _created4; + } + } + + function reconcileSinglePortal( + returnFiber, + currentFirstChild, + portal, + lanes + ) { + var key = portal.key; + var child = currentFirstChild; + + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + if ( + child.tag === HostPortal && + child.stateNode.containerInfo === portal.containerInfo && + child.stateNode.implementation === portal.implementation + ) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, portal.children || []); + existing.return = returnFiber; + return existing; + } else { + deleteRemainingChildren(returnFiber, child); + break; + } + } else { + deleteChild(returnFiber, child); + } + + child = child.sibling; + } + + var created = createFiberFromPortal(portal, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } // This API will tag the children with the side-effect of the reconciliation + // itself. They will be added to the side-effect list as we pass through the + // children and the parent. + + function reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + // This function is not recursive. + // If the top level item is an array, we treat it as a set of children, + // not as a fragment. Nested arrays on the other hand will be treated as + // fragment nodes. Recursion happens at the normal flow. + // Handle top level unkeyed fragments as if they were arrays. + // This leads to an ambiguity between <>{[...]} and <>.... + // We treat the ambiguous cases above the same. + // TODO: Let's use recursion like we do for Usable nodes? + var isUnkeyedTopLevelFragment = + typeof newChild === "object" && + newChild !== null && + newChild.type === REACT_FRAGMENT_TYPE && + newChild.key === null; + + if (isUnkeyedTopLevelFragment) { + newChild = newChild.props.children; + } // Handle object types + + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + return placeSingleChild( + reconcileSingleElement( + returnFiber, + currentFirstChild, + newChild, + lanes + ) + ); + + case REACT_PORTAL_TYPE: + return placeSingleChild( + reconcileSinglePortal( + returnFiber, + currentFirstChild, + newChild, + lanes + ) + ); + + case REACT_LAZY_TYPE: + var payload = newChild._payload; + var init = newChild._init; // TODO: This function is supposed to be non-recursive. + + return reconcileChildFibers( + returnFiber, + currentFirstChild, + init(payload), + lanes + ); + } + + if (isArray(newChild)) { + return reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + } + + if (getIteratorFn(newChild)) { + return reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + } // Usables are a valid React node type. When React encounters a Usable in + // a child position, it unwraps it using the same algorithm as `use`. For + // example, for promises, React will throw an exception to unwind the + // stack, then replay the component once the promise resolves. + // + // A difference from `use` is that React will keep unwrapping the value + // until it reaches a non-Usable type. + // + // e.g. Usable>> should resolve to T + // + // The structure is a bit unfortunate. Ideally, we shouldn't need to + // replay the entire begin phase of the parent fiber in order to reconcile + // the children again. This would require a somewhat significant refactor, + // because reconcilation happens deep within the begin phase, and + // depending on the type of work, not always at the end. We should + // consider as an future improvement. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + unwrapThenable(thenable), + lanes + ); + } + + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } + + throwOnInvalidObjectType(returnFiber, newChild); + } + + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + return placeSingleChild( + reconcileSingleTextNode( + returnFiber, + currentFirstChild, + "" + newChild, + lanes + ) + ); + } + + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } // Remaining cases are all treated as empty. + + return deleteRemainingChildren(returnFiber, currentFirstChild); + } + + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + // This indirection only exists so we can reset `thenableState` at the end. + // It should get inlined by Closure. + thenableIndexCounter$1 = 0; + var firstChildFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + thenableState$1 = null; // Don't bother to reset `thenableIndexCounter` to 0 because it always gets + // set at the beginning. + + return firstChildFiber; + } + + return reconcileChildFibers; + } + + var reconcileChildFibers = createChildReconciler(true); + var mountChildFibers = createChildReconciler(false); + function resetChildReconcilerOnUnwind() { + // On unwind, clear any pending thenables that were used. + thenableState$1 = null; + thenableIndexCounter$1 = 0; + } + function cloneChildFibers(current, workInProgress) { + if (current !== null && workInProgress.child !== current.child) { + throw new Error("Resuming work not yet implemented."); + } + + if (workInProgress.child === null) { + return; + } + + var currentChild = workInProgress.child; + var newChild = createWorkInProgress( + currentChild, + currentChild.pendingProps + ); + workInProgress.child = newChild; + newChild.return = workInProgress; + + while (currentChild.sibling !== null) { + currentChild = currentChild.sibling; + newChild = newChild.sibling = createWorkInProgress( + currentChild, + currentChild.pendingProps + ); + newChild.return = workInProgress; + } + + newChild.sibling = null; + } // Reset a workInProgress child set to prepare it for a second pass. + + function resetChildFibers(workInProgress, lanes) { + var child = workInProgress.child; + + while (child !== null) { + resetWorkInProgress(child, lanes); + child = child.sibling; + } + } + + // TODO: This isn't being used yet, but it's intended to replace the + // InvisibleParentContext that is currently managed by SuspenseContext. + + var currentTreeHiddenStackCursor = createCursor(null); + var prevEntangledRenderLanesCursor = createCursor(NoLanes); + function pushHiddenContext(fiber, context) { + var prevEntangledRenderLanes = getEntangledRenderLanes(); + push(prevEntangledRenderLanesCursor, prevEntangledRenderLanes, fiber); + push(currentTreeHiddenStackCursor, context, fiber); // When rendering a subtree that's currently hidden, we must include all + // lanes that would have rendered if the hidden subtree hadn't been deferred. + // That is, in order to reveal content from hidden -> visible, we must commit + // all the updates that we skipped when we originally hid the tree. + + setEntangledRenderLanes( + mergeLanes(prevEntangledRenderLanes, context.baseLanes) + ); + } + function reuseHiddenContextOnStack(fiber) { + // This subtree is not currently hidden, so we don't need to add any lanes + // to the render lanes. But we still need to push something to avoid a + // context mismatch. Reuse the existing context on the stack. + push(prevEntangledRenderLanesCursor, getEntangledRenderLanes(), fiber); + push( + currentTreeHiddenStackCursor, + currentTreeHiddenStackCursor.current, + fiber + ); + } + function popHiddenContext(fiber) { + // Restore the previous render lanes from the stack + setEntangledRenderLanes(prevEntangledRenderLanesCursor.current); + pop(currentTreeHiddenStackCursor, fiber); + pop(prevEntangledRenderLanesCursor, fiber); + } + function isCurrentTreeHidden() { + return currentTreeHiddenStackCursor.current !== null; + } + + // suspends, i.e. it's the nearest `catch` block on the stack. + + var suspenseHandlerStackCursor = createCursor(null); // Represents the outermost boundary that is not visible in the current tree. + // Everything above this is the "shell". When this is null, it means we're + // rendering in the shell of the app. If it's non-null, it means we're rendering + // deeper than the shell, inside a new tree that wasn't already visible. + // + // The main way we use this concept is to determine whether showing a fallback + // would result in a desirable or undesirable loading state. Activing a fallback + // in the shell is considered an undersirable loading state, because it would + // mean hiding visible (albeit stale) content in the current tree — we prefer to + // show the stale content, rather than switch to a fallback. But showing a + // fallback in a new tree is fine, because there's no stale content to + // prefer instead. + + var shellBoundary = null; + function getShellBoundary() { + return shellBoundary; + } + function pushPrimaryTreeSuspenseHandler(handler) { + // TODO: Pass as argument + var current = handler.alternate; + var props = handler.pendingProps; // Shallow Suspense context fields, like ForceSuspenseFallback, should only be + // propagated a single level. For example, when ForceSuspenseFallback is set, + // it should only force the nearest Suspense boundary into fallback mode. + + pushSuspenseListContext( + handler, + setDefaultShallowSuspenseListContext(suspenseStackCursor.current) + ); // Experimental feature: Some Suspense boundaries are marked as having an + // undesirable fallback state. These have special behavior where we only + // activate the fallback if there's no other boundary on the stack that we can + // use instead. + + if ( + props.unstable_avoidThisFallback === true && // If an avoided boundary is already visible, it behaves identically to + // a regular Suspense boundary. + (current === null || isCurrentTreeHidden()) + ) { + if (shellBoundary === null) { + // We're rendering in the shell. There's no parent Suspense boundary that + // can provide a desirable fallback state. We'll use this boundary. + push(suspenseHandlerStackCursor, handler, handler); // However, because this is not a desirable fallback, the children are + // still considered part of the shell. So we intentionally don't assign + // to `shellBoundary`. + } else { + // There's already a parent Suspense boundary that can provide a desirable + // fallback state. Prefer that one. + var handlerOnStack = suspenseHandlerStackCursor.current; + push(suspenseHandlerStackCursor, handlerOnStack, handler); + } + + return; + } // TODO: If the parent Suspense handler already suspended, there's no reason + // to push a nested Suspense handler, because it will get replaced by the + // outer fallback, anyway. Consider this as a future optimization. + + push(suspenseHandlerStackCursor, handler, handler); + + if (shellBoundary === null) { + if (current === null || isCurrentTreeHidden()) { + // This boundary is not visible in the current UI. + shellBoundary = handler; + } else { + var prevState = current.memoizedState; + + if (prevState !== null) { + // This boundary is showing a fallback in the current UI. + shellBoundary = handler; + } + } + } + } + function pushFallbackTreeSuspenseHandler(fiber) { + // We're about to render the fallback. If something in the fallback suspends, + // it's akin to throwing inside of a `catch` block. This boundary should not + // capture. Reuse the existing handler on the stack. + reuseSuspenseHandlerOnStack(fiber); + } + function pushOffscreenSuspenseHandler(fiber) { + if (fiber.tag === OffscreenComponent) { + // A SuspenseList context is only pushed here to avoid a push/pop mismatch. + // Reuse the current value on the stack. + // TODO: We can avoid needing to push here by by forking popSuspenseHandler + // into separate functions for Suspense and Offscreen. + pushSuspenseListContext(fiber, suspenseStackCursor.current); + push(suspenseHandlerStackCursor, fiber, fiber); + + if (shellBoundary !== null); + else { + var current = fiber.alternate; + + if (current !== null) { + var prevState = current.memoizedState; + + if (prevState !== null) { + // This is the first boundary in the stack that's already showing + // a fallback. So everything outside is considered the shell. + shellBoundary = fiber; + } + } + } + } else { + // This is a LegacyHidden component. + reuseSuspenseHandlerOnStack(fiber); + } + } + function reuseSuspenseHandlerOnStack(fiber) { + pushSuspenseListContext(fiber, suspenseStackCursor.current); + push(suspenseHandlerStackCursor, getSuspenseHandler(), fiber); + } + function getSuspenseHandler() { + return suspenseHandlerStackCursor.current; + } + function popSuspenseHandler(fiber) { + pop(suspenseHandlerStackCursor, fiber); + + if (shellBoundary === fiber) { + // Popping back into the shell. + shellBoundary = null; + } + + popSuspenseListContext(fiber); + } // SuspenseList context + // TODO: Move to a separate module? We may change the SuspenseList + // implementation to hide/show in the commit phase, anyway. + + var DefaultSuspenseContext = 0; + var SubtreeSuspenseContextMask = 1; // ForceSuspenseFallback can be used by SuspenseList to force newly added + // items into their fallback state during one of the render passes. + + var ForceSuspenseFallback = 2; + var suspenseStackCursor = createCursor(DefaultSuspenseContext); + function hasSuspenseListContext(parentContext, flag) { + return (parentContext & flag) !== 0; + } + function setDefaultShallowSuspenseListContext(parentContext) { + return parentContext & SubtreeSuspenseContextMask; + } + function setShallowSuspenseListContext(parentContext, shallowContext) { + return (parentContext & SubtreeSuspenseContextMask) | shallowContext; + } + function pushSuspenseListContext(fiber, newContext) { + push(suspenseStackCursor, newContext, fiber); + } + function popSuspenseListContext(fiber) { + pop(suspenseStackCursor, fiber); + } + + // A non-null SuspenseState means that it is blocked for one reason or another. + // - A non-null dehydrated field means it's blocked pending hydration. + // - A non-null dehydrated field can use isSuspenseInstancePending or + // isSuspenseInstanceFallback to query the reason for being dehydrated. + // - A null dehydrated field means it's blocked by something suspending and + // we're currently showing a fallback instead. + + function findFirstSuspended(row) { + var node = row; + + while (node !== null) { + if (node.tag === SuspenseComponent) { + var state = node.memoizedState; + + if (state !== null) { + var dehydrated = state.dehydrated; + + if ( + dehydrated === null || + isSuspenseInstancePending() || + isSuspenseInstanceFallback() + ) { + return node; + } + } + } else if ( + node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't + // keep track of whether it suspended or not. + node.memoizedProps.revealOrder !== undefined + ) { + var didSuspend = (node.flags & DidCapture) !== NoFlags$1; + + if (didSuspend) { + return node; + } + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } + + if (node === row) { + return null; + } + + while (node.sibling === null) { + if (node.return === null || node.return === row) { + return null; + } + + node = node.return; + } + + node.sibling.return = node.return; + node = node.sibling; + } + + return null; + } + + var NoFlags = + /* */ + 0; // Represents whether effect should fire. + + var HasEffect = + /* */ + 1; // Represents the phase in which the effect (not the clean-up) fires. + + var Insertion = + /* */ + 2; + var Layout = + /* */ + 4; + var Passive = + /* */ + 8; + + var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // A linked list of all the roots with pending work. In an idiomatic app, + // there's only a single root, but we do support multi root apps, hence this + // extra complexity. But this module is optimized for the single root case. + + var firstScheduledRoot = null; + var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. + + var didScheduleMicrotask = false; // `act` "microtasks" are scheduled on the `act` queue instead of an actual + // microtask, so we have to dedupe those separately. This wouldn't be an issue + // if we required all `act` calls to be awaited, which we might in the future. + + var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. + + var mightHavePendingSyncWork = false; + var isFlushingWork = false; + var currentEventTransitionLane = NoLane; + function ensureRootIsScheduled(root) { + // This function is called whenever a root receives an update. It does two + // things 1) it ensures the root is in the root schedule, and 2) it ensures + // there's a pending microtask to process the root schedule. + // + // Most of the actual scheduling logic does not happen until + // `scheduleTaskForRootDuringMicrotask` runs. + // Add the root to the schedule + if (root === lastScheduledRoot || root.next !== null); + else { + if (lastScheduledRoot === null) { + firstScheduledRoot = lastScheduledRoot = root; + } else { + lastScheduledRoot.next = root; + lastScheduledRoot = root; + } + } // Any time a root received an update, we set this to true until the next time + // we process the schedule. If it's false, then we can quickly exit flushSync + // without consulting the schedule. + + mightHavePendingSyncWork = true; // At the end of the current event, go through each of the roots and ensure + // there's a task scheduled for each one at the correct priority. + + if (ReactCurrentActQueue$2.current !== null) { + // We're inside an `act` scope. + if (!didScheduleMicrotask_act) { + didScheduleMicrotask_act = true; + scheduleImmediateTask(processRootScheduleInMicrotask); + } + } else { + if (!didScheduleMicrotask) { + didScheduleMicrotask = true; + scheduleImmediateTask(processRootScheduleInMicrotask); + } + } + + if (!enableDeferRootSchedulingToMicrotask) { + // While this flag is disabled, we schedule the render task immediately + // instead of waiting a microtask. + // TODO: We need to land enableDeferRootSchedulingToMicrotask ASAP to + // unblock additional features we have planned. + scheduleTaskForRootDuringMicrotask(root, now$1()); + } + + if (ReactCurrentActQueue$2.isBatchingLegacy && root.tag === LegacyRoot) { + // Special `act` case: Record whenever a legacy update is scheduled. + ReactCurrentActQueue$2.didScheduleLegacyUpdate = true; + } + } + function flushSyncWorkOnAllRoots() { + // This is allowed to be called synchronously, but the caller should check + // the execution context first. + flushSyncWorkAcrossRoots_impl(false); + } + function flushSyncWorkOnLegacyRootsOnly() { + // This is allowed to be called synchronously, but the caller should check + // the execution context first. + flushSyncWorkAcrossRoots_impl(true); + } + + function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (isFlushingWork) { + // Prevent reentrancy. + // TODO: Is this overly defensive? The callers must check the execution + // context first regardless. + return; + } + + if (!mightHavePendingSyncWork) { + // Fast path. There's no sync work to do. + return; + } // There may or may not be synchronous work scheduled. Let's check. + + var didPerformSomeWork; + var errors = null; + isFlushingWork = true; + + do { + didPerformSomeWork = false; + var root = firstScheduledRoot; + + while (root !== null) { + if (onlyLegacy && root.tag !== LegacyRoot); + else { + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = + getWorkInProgressRootRenderLanes(); + var nextLanes = getNextLanes( + root, + root === workInProgressRoot + ? workInProgressRootRenderLanes + : NoLanes + ); + + if (includesSyncLane(nextLanes)) { + // This root has pending sync work. Flush it now. + try { + didPerformSomeWork = true; + performSyncWorkOnRoot(root, nextLanes); + } catch (error) { + // Collect errors so we can rethrow them at the end + if (errors === null) { + errors = [error]; + } else { + errors.push(error); + } + } + } + } + + root = root.next; + } + } while (didPerformSomeWork); + + isFlushingWork = false; // If any errors were thrown, rethrow them right before exiting. + // TODO: Consider returning these to the caller, to allow them to decide + // how/when to rethrow. + + if (errors !== null) { + if (errors.length > 1) { + if (typeof AggregateError === "function") { + // eslint-disable-next-line no-undef + throw new AggregateError(errors); + } else { + for (var i = 1; i < errors.length; i++) { + scheduleImmediateTask(throwError.bind(null, errors[i])); + } + + var firstError = errors[0]; + throw firstError; + } + } else { + var error = errors[0]; + throw error; + } + } + } + + function throwError(error) { + throw error; + } + + function processRootScheduleInMicrotask() { + // This function is always called inside a microtask. It should never be + // called synchronously. + didScheduleMicrotask = false; + + { + didScheduleMicrotask_act = false; + } // We'll recompute this as we iterate through all the roots and schedule them. + + mightHavePendingSyncWork = false; + var currentTime = now$1(); + var prev = null; + var root = firstScheduledRoot; + + while (root !== null) { + var next = root.next; + + if ( + currentEventTransitionLane !== NoLane && + shouldAttemptEagerTransition() + ) { + // A transition was scheduled during an event, but we're going to try to + // render it synchronously anyway. We do this during a popstate event to + // preserve the scroll position of the previous page. + upgradePendingLaneToSync(root, currentEventTransitionLane); + } + + var nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); + + if (nextLanes === NoLane) { + // This root has no more pending work. Remove it from the schedule. To + // guard against subtle reentrancy bugs, this microtask is the only place + // we do this — you can add roots to the schedule whenever, but you can + // only remove them here. + // Null this out so we know it's been removed from the schedule. + root.next = null; + + if (prev === null) { + // This is the new head of the list + firstScheduledRoot = next; + } else { + prev.next = next; + } + + if (next === null) { + // This is the new tail of the list + lastScheduledRoot = prev; + } + } else { + // This root still has work. Keep it in the list. + prev = root; + + if (includesSyncLane(nextLanes)) { + mightHavePendingSyncWork = true; + } + } + + root = next; + } + + currentEventTransitionLane = NoLane; // At the end of the microtask, flush any pending synchronous work. This has + // to come at the end, because it does actual rendering work that might throw. + + flushSyncWorkOnAllRoots(); + } + + function scheduleTaskForRootDuringMicrotask(root, currentTime) { + // This function is always called inside a microtask, or at the very end of a + // rendering task right before we yield to the main thread. It should never be + // called synchronously. + // + // TODO: Unless enableDeferRootSchedulingToMicrotask is off. We need to land + // that ASAP to unblock additional features we have planned. + // + // This function also never performs React work synchronously; it should + // only schedule work to be performed later, in a separate task or microtask. + // Check if any lanes are being starved by other work. If so, mark them as + // expired so we know to work on those next. + markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. + + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); + var existingCallbackNode = root.callbackNode; + + if ( + // Check if there's nothing to work on + nextLanes === NoLanes || // If this root is currently suspended and waiting for data to resolve, don't + // schedule a task to render it. We'll either wait for a ping, or wait to + // receive an update. + // + // Suspended render phase + (root === workInProgressRoot && isWorkLoopSuspendedOnData()) || // Suspended commit phase + root.cancelPendingCommit !== null + ) { + // Fast path: There's nothing to work on. + if (existingCallbackNode !== null) { + cancelCallback(existingCallbackNode); + } + + root.callbackNode = null; + root.callbackPriority = NoLane; + return NoLane; + } // Schedule a new callback in the host environment. + + if (includesSyncLane(nextLanes)) { + // Synchronous work is always flushed at the end of the microtask, so we + // don't need to schedule an additional task. + if (existingCallbackNode !== null) { + cancelCallback(existingCallbackNode); + } + + root.callbackPriority = SyncLane; + root.callbackNode = null; + return SyncLane; + } else { + // We use the highest priority lane to represent the priority of the callback. + var existingCallbackPriority = root.callbackPriority; + var newCallbackPriority = getHighestPriorityLane(nextLanes); + + if ( + newCallbackPriority === existingCallbackPriority && // Special case related to `act`. If the currently scheduled task is a + // Scheduler task, rather than an `act` task, cancel it and re-schedule + // on the `act` queue. + !( + ReactCurrentActQueue$2.current !== null && + existingCallbackNode !== fakeActCallbackNode$1 + ) + ) { + // The priority hasn't changed. We can reuse the existing task. + return newCallbackPriority; + } else { + // Cancel the existing callback. We'll schedule a new one below. + cancelCallback(existingCallbackNode); + } + + var schedulerPriorityLevel; + + switch (lanesToEventPriority(nextLanes)) { + case DiscreteEventPriority: + schedulerPriorityLevel = ImmediatePriority; + break; + + case ContinuousEventPriority: + schedulerPriorityLevel = UserBlockingPriority; + break; + + case DefaultEventPriority: + schedulerPriorityLevel = NormalPriority$1; + break; + + case IdleEventPriority: + schedulerPriorityLevel = IdlePriority; + break; + + default: + schedulerPriorityLevel = NormalPriority$1; + break; + } + + var newCallbackNode = scheduleCallback$2( + schedulerPriorityLevel, + performConcurrentWorkOnRoot.bind(null, root) + ); + root.callbackPriority = newCallbackPriority; + root.callbackNode = newCallbackNode; + return newCallbackPriority; + } + } + + function getContinuationForRoot(root, originalCallbackNode) { + // This is called at the end of `performConcurrentWorkOnRoot` to determine + // if we need to schedule a continuation task. + // + // Usually `scheduleTaskForRootDuringMicrotask` only runs inside a microtask; + // however, since most of the logic for determining if we need a continuation + // versus a new task is the same, we cheat a bit and call it here. This is + // only safe to do because we know we're at the end of the browser task. + // So although it's not an actual microtask, it might as well be. + scheduleTaskForRootDuringMicrotask(root, now$1()); + + if (root.callbackNode === originalCallbackNode) { + // The task node scheduled for this root is the same one that's + // currently executed. Need to return a continuation. + return performConcurrentWorkOnRoot.bind(null, root); + } + + return null; + } + var fakeActCallbackNode$1 = {}; + + function scheduleCallback$2(priorityLevel, callback) { + if (ReactCurrentActQueue$2.current !== null) { + // Special case: We're inside an `act` scope (a testing utility). + // Instead of scheduling work in the host environment, add it to a + // fake internal queue that's managed by the `act` implementation. + ReactCurrentActQueue$2.current.push(callback); + return fakeActCallbackNode$1; + } else { + return scheduleCallback$3(priorityLevel, callback); + } + } + + function cancelCallback(callbackNode) { + if (callbackNode === fakeActCallbackNode$1); + else if (callbackNode !== null) { + cancelCallback$1(callbackNode); + } + } + + function scheduleImmediateTask(cb) { + if (ReactCurrentActQueue$2.current !== null) { + // Special case: Inside an `act` scope, we push microtasks to the fake `act` + // callback queue. This is because we currently support calling `act` + // without awaiting the result. The plan is to deprecate that, and require + // that you always await the result so that the microtasks have a chance to + // run. But it hasn't happened yet. + ReactCurrentActQueue$2.current.push(function () { + cb(); + return null; + }); + } // TODO: Can we land supportsMicrotasks? Which environments don't support it? + // Alternatively, can we move this check to the host config? + + { + // If microtasks are not supported, use Scheduler. + scheduleCallback$3(ImmediatePriority, cb); + } + } + + function requestTransitionLane() { + // The algorithm for assigning an update to a lane should be stable for all + // updates at the same priority within the same event. To do this, the + // inputs to the algorithm must be the same. + // + // The trick we use is to cache the first of each of these inputs within an + // event. Then reset the cached values once we can be sure the event is + // over. Our heuristic for that is whenever we enter a concurrent work loop. + if (currentEventTransitionLane === NoLane) { + // All transitions within the same event are assigned the same lane. + currentEventTransitionLane = claimNextTransitionLane(); + } + + return currentEventTransitionLane; + } + + // transition updates that occur while the async action is still in progress + // are treated as part of the action. + // + // The ideal behavior would be to treat each async function as an independent + // action. However, without a mechanism like AsyncContext, we can't tell which + // action an update corresponds to. So instead, we entangle them all into one. + // The listeners to notify once the entangled scope completes. + + var currentEntangledListeners = null; // The number of pending async actions in the entangled scope. + + var currentEntangledPendingCount = 0; // The transition lane shared by all updates in the entangled scope. + + var currentEntangledLane = NoLane; + function requestAsyncActionContext( + actionReturnValue, // If this is provided, this resulting thenable resolves to this value instead + // of the return value of the action. This is a perf trick to avoid composing + // an extra async function. + overrideReturnValue + ) { + // This is an async action. + // + // Return a thenable that resolves once the action scope (i.e. the async + // function passed to startTransition) has finished running. + var thenable = actionReturnValue; + var entangledListeners; + + if (currentEntangledListeners === null) { + // There's no outer async action scope. Create a new one. + entangledListeners = currentEntangledListeners = []; + currentEntangledPendingCount = 0; + currentEntangledLane = requestTransitionLane(); + } else { + entangledListeners = currentEntangledListeners; + } + + currentEntangledPendingCount++; // Create a thenable that represents the result of this action, but doesn't + // resolve until the entire entangled scope has finished. + // + // Expressed using promises: + // const [thisResult] = await Promise.all([thisAction, entangledAction]); + // return thisResult; + + var resultThenable = createResultThenable(entangledListeners); + var resultStatus = "pending"; + var resultValue; + var rejectedReason; + thenable.then( + function (value) { + resultStatus = "fulfilled"; + resultValue = + overrideReturnValue !== null ? overrideReturnValue : value; + pingEngtangledActionScope(); + }, + function (error) { + resultStatus = "rejected"; + rejectedReason = error; + pingEngtangledActionScope(); + } + ); // Attach a listener to fill in the result. + + entangledListeners.push(function () { + switch (resultStatus) { + case "fulfilled": { + var fulfilledThenable = resultThenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = resultValue; + break; + } + + case "rejected": { + var rejectedThenable = resultThenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = rejectedReason; + break; + } + + case "pending": + default: { + // The listener above should have been called first, so `resultStatus` + // should already be set to the correct value. + throw new Error( + "Thenable should have already resolved. This " + + "is a bug in React." + ); + } + } + }); + return resultThenable; + } + function requestSyncActionContext( + actionReturnValue, // If this is provided, this resulting thenable resolves to this value instead + // of the return value of the action. This is a perf trick to avoid composing + // an extra async function. + overrideReturnValue + ) { + var resultValue = + overrideReturnValue !== null ? overrideReturnValue : actionReturnValue; // This is not an async action, but it may be part of an outer async action. + + if (currentEntangledListeners === null) { + return resultValue; + } else { + // Return a thenable that does not resolve until the entangled actions + // have finished. + var entangledListeners = currentEntangledListeners; + var resultThenable = createResultThenable(entangledListeners); + entangledListeners.push(function () { + var fulfilledThenable = resultThenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = resultValue; + }); + return resultThenable; + } + } + + function pingEngtangledActionScope() { + if ( + currentEntangledListeners !== null && + --currentEntangledPendingCount === 0 + ) { + // All the actions have finished. Close the entangled async action scope + // and notify all the listeners. + var listeners = currentEntangledListeners; + currentEntangledListeners = null; + currentEntangledLane = NoLane; + + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; + listener(); + } + } + } + + function createResultThenable(entangledListeners) { + // Waits for the entangled async action to complete, then resolves to the + // result of an individual action. + var resultThenable = { + status: "pending", + value: null, + reason: null, + then: function (resolve) { + // This is a bit of a cheat. `resolve` expects a value of type `S` to be + // passed, but because we're instrumenting the `status` field ourselves, + // and we know this thenable will only be used by React, we also know + // the value isn't actually needed. So we add the resolve function + // directly to the entangled listeners. + // + // This is also why we don't need to check if the thenable is still + // pending; the Suspense implementation already performs that check. + var ping = resolve; + entangledListeners.push(ping); + } + }; + return resultThenable; + } + + function peekEntangledActionLane() { + return currentEntangledLane; + } + + var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, + ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig; + var didWarnAboutMismatchedHooksForComponent; + var didWarnUncachedGetSnapshot; + var didWarnAboutUseWrappedInTryCatch; + var didWarnAboutAsyncClientComponent; + + { + didWarnAboutMismatchedHooksForComponent = new Set(); + didWarnAboutUseWrappedInTryCatch = new Set(); + didWarnAboutAsyncClientComponent = new Set(); + } // The effect "instance" is a shared object that remains the same for the entire + // lifetime of an effect. In Rust terms, a RefCell. We use it to store the + // "destroy" function that is returned from an effect, because that is stateful. + // The field is `undefined` if the effect is unmounted, or if the effect ran + // but is not stateful. We don't explicitly track whether the effect is mounted + // or unmounted because that can be inferred by the hiddenness of the fiber in + // the tree, i.e. whether there is a hidden Offscreen fiber above it. + // + // It's unfortunate that this is stored on a separate object, because it adds + // more memory per effect instance, but it's conceptually sound. I think there's + // likely a better data structure we could use for effects; perhaps just one + // array of effect instances per fiber. But I think this is OK for now despite + // the additional memory and we can follow up with performance + // optimizations later. + // These are set right before calling the component. + + var renderLanes = NoLanes; // The work-in-progress fiber. I've named it differently to distinguish it from + // the work-in-progress hook. + + var currentlyRenderingFiber$1 = null; // Hooks are stored as a linked list on the fiber's memoizedState field. The + // current hook list is the list that belongs to the current fiber. The + // work-in-progress hook list is a new list that will be added to the + // work-in-progress fiber. + + var currentHook = null; + var workInProgressHook = null; // Whether an update was scheduled at any point during the render phase. This + // does not get reset if we do another render pass; only when we're completely + // finished evaluating this component. This is an optimization so we know + // whether we need to clear render phase updates after a throw. + + var didScheduleRenderPhaseUpdate = false; // Where an update was scheduled only during the current render pass. This + // gets reset after each attempt. + // TODO: Maybe there's some way to consolidate this with + // `didScheduleRenderPhaseUpdate`. Or with `numberOfReRenders`. + + var didScheduleRenderPhaseUpdateDuringThisPass = false; + var shouldDoubleInvokeUserFnsInHooksDEV = false; // Counts the number of useId hooks in this component. + + var thenableIndexCounter = 0; + var thenableState = null; // Used for ids that are generated completely client-side (i.e. not during + // hydration). This counter is global, so client ids are not stable across + // render attempts. + + var globalClientIdCounter = 0; + var RE_RENDER_LIMIT = 25; // In DEV, this is the name of the currently executing primitive hook + + var currentHookNameInDev = null; // In DEV, this list ensures that hooks are called in the same order between renders. + // The list stores the order of hooks used during the initial render (mount). + // Subsequent renders (updates) reference this list. + + var hookTypesDev = null; + var hookTypesUpdateIndexDev = -1; // In DEV, this tracks whether currently rendering component needs to ignore + // the dependencies for Hooks that need them (e.g. useEffect or useMemo). + // When true, such Hooks will always be "remounted". Only used during hot reload. + + var ignorePreviousDependencies = false; + + function mountHookTypesDev() { + { + var hookName = currentHookNameInDev; + + if (hookTypesDev === null) { + hookTypesDev = [hookName]; + } else { + hookTypesDev.push(hookName); + } + } + } + + function updateHookTypesDev() { + { + var hookName = currentHookNameInDev; + + if (hookTypesDev !== null) { + hookTypesUpdateIndexDev++; + + if (hookTypesDev[hookTypesUpdateIndexDev] !== hookName) { + warnOnHookMismatchInDev(hookName); + } + } + } + } + + function checkDepsAreArrayDev(deps) { + { + if (deps !== undefined && deps !== null && !isArray(deps)) { + // Verify deps, but only on mount to avoid extra checks. + // It's unlikely their type would change as usually you define them inline. + 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 + ); + } + } + } + + function warnOnHookMismatchInDev(currentHookName) { + { + var componentName = getComponentNameFromFiber( + currentlyRenderingFiber$1 + ); + + if (!didWarnAboutMismatchedHooksForComponent.has(componentName)) { + didWarnAboutMismatchedHooksForComponent.add(componentName); + + if (hookTypesDev !== null) { + var table = ""; + var secondColumnStart = 30; + + for (var i = 0; i <= hookTypesUpdateIndexDev; i++) { + var oldHookName = hookTypesDev[i]; + var newHookName = + i === hookTypesUpdateIndexDev ? currentHookName : oldHookName; + var row = i + 1 + ". " + oldHookName; // Extra space so second column lines up + // lol @ IE not supporting String#repeat + + while (row.length < secondColumnStart) { + row += " "; + } + + row += newHookName + "\n"; + table += row; + } + + 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 + ); + } + } + } + } + + function warnIfAsyncClientComponent(Component, componentDoesIncludeHooks) { + { + // This dev-only check only works for detecting native async functions, + // not transpiled ones. There's also a prod check that we use to prevent + // async client components from crashing the app; the prod one works even + // for transpiled async functions. Neither mechanism is completely + // bulletproof but together they cover the most common cases. + var isAsyncFunction = // $FlowIgnore[method-unbinding] + Object.prototype.toString.call(Component) === + "[object AsyncFunction]"; + + if (isAsyncFunction) { + // Encountered an async Client Component. This is not yet supported, + // except in certain constrained cases, like during a route navigation. + var componentName = getComponentNameFromFiber( + currentlyRenderingFiber$1 + ); + + if (!didWarnAboutAsyncClientComponent.has(componentName)) { + didWarnAboutAsyncClientComponent.add(componentName); // Check if this is a sync update. We use the "root" render lanes here + // because the "subtree" render lanes may include additional entangled + // lanes related to revealing previously hidden content. + + var root = getWorkInProgressRoot(); + var rootRenderLanes = getWorkInProgressRootRenderLanes(); + + if (root !== null && includesBlockingLane(root, rootRenderLanes)) { + error( + "async/await is not yet supported in Client Components, only " + + "Server Components. This error is often caused by accidentally " + + "adding `'use client'` to a module that was originally written " + + "for the server." + ); + } else { + // This is a concurrent (Transition, Retry, etc) render. We don't + // warn in these cases. + // + // However, Async Components are forbidden to include hooks, even + // during a transition, so let's check for that here. + // + // TODO: Add a corresponding warning to Server Components runtime. + if (componentDoesIncludeHooks) { + error( + "Hooks are not supported inside an async component. This " + + "error is often caused by accidentally adding `'use client'` " + + "to a module that was originally written for the server." + ); + } + } + } + } + } + } + + function throwInvalidHookError() { + 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." + ); + } + + function areHookInputsEqual(nextDeps, prevDeps) { + { + if (ignorePreviousDependencies) { + // Only true when this component is being hot reloaded. + return false; + } + } + + if (prevDeps === null) { + { + 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 + ); + } + + return false; + } + + { + // Don't bother comparing lengths in prod because these arrays should be + // passed inline. + if (nextDeps.length !== prevDeps.length) { + 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(", ") + "]" + ); + } + } // $FlowFixMe[incompatible-use] found when upgrading Flow + + for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + if (objectIs(nextDeps[i], prevDeps[i])) { + continue; + } + + return false; + } + + return true; + } + + function renderWithHooks( + current, + workInProgress, + Component, + props, + secondArg, + nextRenderLanes + ) { + renderLanes = nextRenderLanes; + currentlyRenderingFiber$1 = workInProgress; + + { + hookTypesDev = current !== null ? current._debugHookTypes : null; + hookTypesUpdateIndexDev = -1; // Used for hot reloading: + + ignorePreviousDependencies = + current !== null && current.type !== workInProgress.type; + } + + workInProgress.memoizedState = null; + workInProgress.updateQueue = null; + workInProgress.lanes = NoLanes; // The following should have already been reset + // currentHook = null; + // workInProgressHook = null; + // didScheduleRenderPhaseUpdate = false; + // localIdCounter = 0; + // thenableIndexCounter = 0; + // thenableState = null; + // TODO Warn if no hooks are used at all during mount, then some are used during update. + // Currently we will identify the update render as a mount because memoizedState === null. + // This is tricky because it's valid for certain types of components (e.g. React.lazy) + // Using memoizedState to differentiate between mount/update only works if at least one stateful hook is used. + // Non-stateful hooks (e.g. context) don't get added to memoizedState, + // so memoizedState would be null during updates and mounts. + + { + if (current !== null && current.memoizedState !== null) { + ReactCurrentDispatcher$1.current = HooksDispatcherOnUpdateInDEV; + } else if (hookTypesDev !== null) { + // This dispatcher handles an edge case where a component is updating, + // but no stateful hooks have been used. + // We want to match the production code behavior (which will use HooksDispatcherOnMount), + // but with the extra DEV validation to ensure hooks ordering hasn't changed. + // This dispatcher does that. + ReactCurrentDispatcher$1.current = + HooksDispatcherOnMountWithHookTypesInDEV; + } else { + ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; + } + } // In Strict Mode, during development, user functions are double invoked to + // help detect side effects. The logic for how this is implemented for in + // hook components is a bit complex so let's break it down. + // + // We will invoke the entire component function twice. However, during the + // second invocation of the component, the hook state from the first + // invocation will be reused. That means things like `useMemo` functions won't + // run again, because the deps will match and the memoized result will + // be reused. + // + // We want memoized functions to run twice, too, so account for this, user + // functions are double invoked during the *first* invocation of the component + // function, and are *not* double invoked during the second incovation: + // + // - First execution of component function: user functions are double invoked + // - Second execution of component function (in Strict Mode, during + // development): user functions are not double invoked. + // + // This is intentional for a few reasons; most importantly, it's because of + // how `use` works when something suspends: it reuses the promise that was + // passed during the first attempt. This is itself a form of memoization. + // We need to be able to memoize the reactive inputs to the `use` call using + // a hook (i.e. `useMemo`), which means, the reactive inputs to `use` must + // come from the same component invocation as the output. + // + // There are plenty of tests to ensure this behavior is correct. + + var shouldDoubleRenderDEV = + (workInProgress.mode & StrictLegacyMode) !== NoMode; + shouldDoubleInvokeUserFnsInHooksDEV = shouldDoubleRenderDEV; + var children = Component(props, secondArg); + shouldDoubleInvokeUserFnsInHooksDEV = false; // Check if there was a render phase update + + if (didScheduleRenderPhaseUpdateDuringThisPass) { + // Keep rendering until the component stabilizes (there are no more render + // phase updates). + children = renderWithHooksAgain( + workInProgress, + Component, + props, + secondArg + ); + } + + if (shouldDoubleRenderDEV) { + // In development, components are invoked twice to help detect side effects. + setIsStrictModeForDevtools(true); + + try { + children = renderWithHooksAgain( + workInProgress, + Component, + props, + secondArg + ); + } finally { + setIsStrictModeForDevtools(false); + } + } + + finishRenderingHooks(current, workInProgress, Component); + return children; + } + + function finishRenderingHooks(current, workInProgress, Component) { + { + workInProgress._debugHookTypes = hookTypesDev; + var componentDoesIncludeHooks = + workInProgressHook !== null || thenableIndexCounter !== 0; + warnIfAsyncClientComponent(Component, componentDoesIncludeHooks); + } // We can assume the previous dispatcher is always this one, since we set it + // at the beginning of the render phase and there's no re-entrance. + + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; // This check uses currentHook so that it works the same in DEV and prod bundles. + // hookTypesDev could catch more cases (e.g. context) but only in DEV bundles. + + var didRenderTooFewHooks = + currentHook !== null && currentHook.next !== null; + renderLanes = NoLanes; + currentlyRenderingFiber$1 = null; + currentHook = null; + workInProgressHook = null; + + { + currentHookNameInDev = null; + hookTypesDev = null; + hookTypesUpdateIndexDev = -1; // Confirm that a static flag was not added or removed since the last + // render. If this fires, it suggests that we incorrectly reset the static + // flags in some other part of the codebase. This has happened before, for + // example, in the SuspenseList implementation. + + if ( + current !== null && + (current.flags & StaticMask) !== + (workInProgress.flags & StaticMask) && // Disable this warning in legacy mode, because legacy Suspense is weird + // and creates false positives. To make this work in legacy mode, we'd + // need to mark fibers that commit in an incomplete state, somehow. For + // now I'll disable the warning that most of the bugs that would trigger + // it are either exclusive to concurrent mode or exist in both. + (current.mode & ConcurrentMode) !== NoMode + ) { + error( + "Internal React error: Expected static flag was missing. Please " + + "notify the React team." + ); + } + } + + didScheduleRenderPhaseUpdate = false; // This is reset by checkDidRenderIdHook + // localIdCounter = 0; + + thenableIndexCounter = 0; + thenableState = null; + + if (didRenderTooFewHooks) { + throw new Error( + "Rendered fewer hooks than expected. This may be caused by an accidental " + + "early return statement." + ); + } + + if (enableLazyContextPropagation) { + if (current !== null) { + if (!checkIfWorkInProgressReceivedUpdate()) { + // If there were no changes to props or state, we need to check if there + // was a context change. We didn't already do this because there's no + // 1:1 correspondence between dependencies and hooks. Although, because + // there almost always is in the common case (`readContext` is an + // internal API), we could compare in there. OTOH, we only hit this case + // if everything else bails out, so on the whole it might be better to + // keep the comparison out of the common path. + var currentDependencies = current.dependencies; + + if ( + currentDependencies !== null && + checkIfContextChanged(currentDependencies) + ) { + markWorkInProgressReceivedUpdate(); + } + } + } + } + + { + if (checkIfUseWrappedInTryCatch()) { + var componentName = + getComponentNameFromFiber(workInProgress) || "Unknown"; + + if ( + !didWarnAboutUseWrappedInTryCatch.has(componentName) && // This warning also fires if you suspend with `use` inside an + // async component. Since we warn for that above, we'll silence this + // second warning by checking here. + !didWarnAboutAsyncClientComponent.has(componentName) + ) { + didWarnAboutUseWrappedInTryCatch.add(componentName); + + error( + "`use` was called from inside a try/catch block. This is not allowed " + + "and can lead to unexpected behavior. To handle errors triggered " + + "by `use`, wrap your component in a error boundary." + ); + } + } + } + } + + function replaySuspendedComponentWithHooks( + current, + workInProgress, + Component, + props, + secondArg + ) { + // This function is used to replay a component that previously suspended, + // after its data resolves. + // + // It's a simplified version of renderWithHooks, but it doesn't need to do + // most of the set up work because they weren't reset when we suspended; they + // only get reset when the component either completes (finishRenderingHooks) + // or unwinds (resetHooksOnUnwind). + { + hookTypesUpdateIndexDev = -1; // Used for hot reloading: + + ignorePreviousDependencies = + current !== null && current.type !== workInProgress.type; + } + + var children = renderWithHooksAgain( + workInProgress, + Component, + props, + secondArg + ); + finishRenderingHooks(current, workInProgress, Component); + return children; + } + + function renderWithHooksAgain(workInProgress, Component, props, secondArg) { + // This is used to perform another render pass. It's used when setState is + // called during render, and for double invoking components in Strict Mode + // during development. + // + // The state from the previous pass is reused whenever possible. So, state + // updates that were already processed are not processed again, and memoized + // functions (`useMemo`) are not invoked again. + // + // Keep rendering in a loop for as long as render phase updates continue to + // be scheduled. Use a counter to prevent infinite loops. + currentlyRenderingFiber$1 = workInProgress; + var numberOfReRenders = 0; + var children; + + do { + if (didScheduleRenderPhaseUpdateDuringThisPass) { + // It's possible that a use() value depended on a state that was updated in + // this rerender, so we need to watch for different thenables this time. + thenableState = null; + } + + thenableIndexCounter = 0; + didScheduleRenderPhaseUpdateDuringThisPass = false; + + if (numberOfReRenders >= RE_RENDER_LIMIT) { + throw new Error( + "Too many re-renders. React limits the number of renders to prevent " + + "an infinite loop." + ); + } + + numberOfReRenders += 1; + + { + // Even when hot reloading, allow dependencies to stabilize + // after first render to prevent infinite render phase updates. + ignorePreviousDependencies = false; + } // Start over from the beginning of the list + + currentHook = null; + workInProgressHook = null; + workInProgress.updateQueue = null; + + { + // Also validate hook order for cascading updates. + hookTypesUpdateIndexDev = -1; + } + + ReactCurrentDispatcher$1.current = HooksDispatcherOnRerenderInDEV; + children = Component(props, secondArg); + } while (didScheduleRenderPhaseUpdateDuringThisPass); + + return children; + } + function bailoutHooks(current, workInProgress, lanes) { + workInProgress.updateQueue = current.updateQueue; // TODO: Don't need to reset the flags here, because they're reset in the + // complete phase (bubbleProperties). + + if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { + workInProgress.flags &= ~( + MountPassiveDev | + MountLayoutDev | + Passive$1 | + Update + ); + } else { + workInProgress.flags &= ~(Passive$1 | Update); + } + + current.lanes = removeLanes(current.lanes, lanes); + } + function resetHooksAfterThrow() { + // This is called immediaetly after a throw. It shouldn't reset the entire + // module state, because the work loop might decide to replay the component + // again without rewinding. + // + // It should only reset things like the current dispatcher, to prevent hooks + // from being called outside of a component. + currentlyRenderingFiber$1 = null; // We can assume the previous dispatcher is always this one, since we set it + // at the beginning of the render phase and there's no re-entrance. + + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; + } + function resetHooksOnUnwind(workInProgress) { + if (didScheduleRenderPhaseUpdate) { + // There were render phase updates. These are only valid for this render + // phase, which we are now aborting. Remove the updates from the queues so + // they do not persist to the next render. Do not remove updates from hooks + // that weren't processed. + // + // Only reset the updates from the queue if it has a clone. If it does + // not have a clone, that means it wasn't processed, and the updates were + // scheduled before we entered the render phase. + var hook = workInProgress.memoizedState; + + while (hook !== null) { + var queue = hook.queue; + + if (queue !== null) { + queue.pending = null; + } + + hook = hook.next; + } + + didScheduleRenderPhaseUpdate = false; + } + + renderLanes = NoLanes; + currentlyRenderingFiber$1 = null; + currentHook = null; + workInProgressHook = null; + + { + hookTypesDev = null; + hookTypesUpdateIndexDev = -1; + currentHookNameInDev = null; + } + + didScheduleRenderPhaseUpdateDuringThisPass = false; + thenableIndexCounter = 0; + thenableState = null; + } + + function mountWorkInProgressHook() { + var hook = { + memoizedState: null, + baseState: null, + baseQueue: null, + queue: null, + next: null + }; + + if (workInProgressHook === null) { + // This is the first hook in the list + currentlyRenderingFiber$1.memoizedState = workInProgressHook = hook; + } else { + // Append to the end of the list + workInProgressHook = workInProgressHook.next = hook; + } + + return workInProgressHook; + } + + function updateWorkInProgressHook() { + // This function is used both for updates and for re-renders triggered by a + // render phase update. It assumes there is either a current hook we can + // clone, or a work-in-progress hook from a previous render pass that we can + // use as a base. + var nextCurrentHook; + + if (currentHook === null) { + var current = currentlyRenderingFiber$1.alternate; + + if (current !== null) { + nextCurrentHook = current.memoizedState; + } else { + nextCurrentHook = null; + } + } else { + nextCurrentHook = currentHook.next; + } + + var nextWorkInProgressHook; + + if (workInProgressHook === null) { + nextWorkInProgressHook = currentlyRenderingFiber$1.memoizedState; + } else { + nextWorkInProgressHook = workInProgressHook.next; + } + + if (nextWorkInProgressHook !== null) { + // There's already a work-in-progress. Reuse it. + workInProgressHook = nextWorkInProgressHook; + nextWorkInProgressHook = workInProgressHook.next; + currentHook = nextCurrentHook; + } else { + // Clone from the current hook. + if (nextCurrentHook === null) { + var currentFiber = currentlyRenderingFiber$1.alternate; + + if (currentFiber === null) { + // This is the initial render. This branch is reached when the component + // suspends, resumes, then renders an additional hook. + // Should never be reached because we should switch to the mount dispatcher first. + throw new Error( + "Update hook called on initial render. This is likely a bug in React. Please file an issue." + ); + } else { + // This is an update. We should always have a current hook. + throw new Error( + "Rendered more hooks than during the previous render." + ); + } + } + + currentHook = nextCurrentHook; + var newHook = { + memoizedState: currentHook.memoizedState, + baseState: currentHook.baseState, + baseQueue: currentHook.baseQueue, + queue: currentHook.queue, + next: null + }; + + if (workInProgressHook === null) { + // This is the first hook in the list. + currentlyRenderingFiber$1.memoizedState = workInProgressHook = + newHook; + } else { + // Append to the end of the list. + workInProgressHook = workInProgressHook.next = newHook; + } + } + + return workInProgressHook; + } // NOTE: defining two versions of this function to avoid size impact when this feature is disabled. + // Previously this function was inlined, the additional `memoCache` property makes it not inlined. + + var createFunctionComponentUpdateQueue; + + { + createFunctionComponentUpdateQueue = function () { + return { + lastEffect: null, + events: null, + stores: null, + memoCache: null + }; + }; + } + + function useThenable(thenable) { + // Track the position of the thenable within this fiber. + var index = thenableIndexCounter; + thenableIndexCounter += 1; + + if (thenableState === null) { + thenableState = createThenableState(); + } + + var result = trackUsedThenable(thenableState, thenable, index); + + if ( + currentlyRenderingFiber$1.alternate === null && + (workInProgressHook === null + ? currentlyRenderingFiber$1.memoizedState === null + : workInProgressHook.next === null) + ) { + // Initial render, and either this is the first time the component is + // called, or there were no Hooks called after this use() the previous + // time (perhaps because it threw). Subsequent Hook calls should use the + // mount dispatcher. + { + ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; + } + } + + return result; + } + + function use(usable) { + if (usable !== null && typeof usable === "object") { + // $FlowFixMe[method-unbinding] + if (typeof usable.then === "function") { + // This is a thenable. + var thenable = usable; + return useThenable(thenable); + } else if ( + usable.$$typeof === REACT_CONTEXT_TYPE || + usable.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = usable; + return readContext(context); + } + } // eslint-disable-next-line react-internal/safe-string-coercion + + throw new Error( + "An unsupported type was passed to use(): " + String(usable) + ); + } + + function useMemoCache(size) { + var memoCache = null; // Fast-path, load memo cache from wip fiber if already prepared + + var updateQueue = currentlyRenderingFiber$1.updateQueue; + + if (updateQueue !== null) { + memoCache = updateQueue.memoCache; + } // Otherwise clone from the current fiber + + if (memoCache == null) { + var current = currentlyRenderingFiber$1.alternate; + + if (current !== null) { + var currentUpdateQueue = current.updateQueue; + + if (currentUpdateQueue !== null) { + var currentMemoCache = currentUpdateQueue.memoCache; + + if (currentMemoCache != null) { + memoCache = { + data: currentMemoCache.data.map(function (array) { + return array.slice(); + }), + index: 0 + }; + } + } + } + } // Finally fall back to allocating a fresh instance of the cache + + if (memoCache == null) { + memoCache = { + data: [], + index: 0 + }; + } + + if (updateQueue === null) { + updateQueue = createFunctionComponentUpdateQueue(); + currentlyRenderingFiber$1.updateQueue = updateQueue; + } + + updateQueue.memoCache = memoCache; + var data = memoCache.data[memoCache.index]; + + if (data === undefined) { + data = memoCache.data[memoCache.index] = new Array(size); + + for (var i = 0; i < size; i++) { + data[i] = REACT_MEMO_CACHE_SENTINEL; + } + } else if (data.length !== size) { + // TODO: consider warning or throwing here + { + error( + "Expected a constant size argument for each invocation of useMemoCache. " + + "The previous cache was allocated with size %s but size %s was requested.", + data.length, + size + ); + } + } + + memoCache.index++; + return data; + } + + function basicStateReducer(state, action) { + // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types + return typeof action === "function" ? action(state) : action; + } + + function mountReducer(reducer, initialArg, init) { + var hook = mountWorkInProgressHook(); + var initialState; + + if (init !== undefined) { + initialState = init(initialArg); + } else { + initialState = initialArg; + } + + hook.memoizedState = hook.baseState = initialState; + var queue = { + pending: null, + lanes: NoLanes, + dispatch: null, + lastRenderedReducer: reducer, + lastRenderedState: initialState + }; + hook.queue = queue; + var dispatch = (queue.dispatch = dispatchReducerAction.bind( + null, + currentlyRenderingFiber$1, + queue + )); + return [hook.memoizedState, dispatch]; + } + + function updateReducer(reducer, initialArg, init) { + var hook = updateWorkInProgressHook(); + return updateReducerImpl(hook, currentHook, reducer); + } + + function updateReducerImpl(hook, current, reducer) { + var queue = hook.queue; + + if (queue === null) { + throw new Error( + "Should have a queue. This is likely a bug in React. Please file an issue." + ); + } + + queue.lastRenderedReducer = reducer; // The last rebase update that is NOT part of the base state. + + var baseQueue = hook.baseQueue; // The last pending update that hasn't been processed yet. + + var pendingQueue = queue.pending; + + if (pendingQueue !== null) { + // We have new updates that haven't been processed yet. + // We'll add them to the base queue. + if (baseQueue !== null) { + // Merge the pending queue and the base queue. + var baseFirst = baseQueue.next; + var pendingFirst = pendingQueue.next; + baseQueue.next = pendingFirst; + pendingQueue.next = baseFirst; + } + + { + if (current.baseQueue !== baseQueue) { + // Internal invariant that should never happen, but feasibly could in + // the future if we implement resuming, or some form of that. + error( + "Internal error: Expected work-in-progress queue to be a clone. " + + "This is a bug in React." + ); + } + } + + current.baseQueue = baseQueue = pendingQueue; + queue.pending = null; + } + + if (baseQueue !== null) { + // We have a queue to process. + var first = baseQueue.next; + var newState = hook.baseState; + var newBaseState = null; + var newBaseQueueFirst = null; + var newBaseQueueLast = null; + var update = first; + + do { + // An extra OffscreenLane bit is added to updates that were made to + // a hidden tree, so that we can distinguish them from updates that were + // already there when the tree was hidden. + var updateLane = removeLanes(update.lane, OffscreenLane); + var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then + // it's not a "base" update and we should disregard the extra base lanes + // that were added to renderLanes when we entered the Offscreen tree. + + var shouldSkipUpdate = isHiddenUpdate + ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) + : !isSubsetOfLanes(renderLanes, updateLane); + + if (shouldSkipUpdate) { + // Priority is insufficient. Skip this update. If this is the first + // skipped update, the previous update/state is the new base + // update/state. + var clone = { + lane: updateLane, + revertLane: update.revertLane, + action: update.action, + hasEagerState: update.hasEagerState, + eagerState: update.eagerState, + next: null + }; + + if (newBaseQueueLast === null) { + newBaseQueueFirst = newBaseQueueLast = clone; + newBaseState = newState; + } else { + newBaseQueueLast = newBaseQueueLast.next = clone; + } // Update the remaining priority in the queue. + // TODO: Don't need to accumulate this. Instead, we can remove + // renderLanes from the original lanes. + + currentlyRenderingFiber$1.lanes = mergeLanes( + currentlyRenderingFiber$1.lanes, + updateLane + ); + markSkippedUpdateLanes(updateLane); + } else { + // This update does have sufficient priority. + // Check if this is an optimistic update. + var revertLane = update.revertLane; + + if (!enableAsyncActions || revertLane === NoLane) { + // This is not an optimistic update, and we're going to apply it now. + // But, if there were earlier updates that were skipped, we need to + // leave this update in the queue so it can be rebased later. + if (newBaseQueueLast !== null) { + var _clone = { + // This update is going to be committed so we never want uncommit + // it. Using NoLane works because 0 is a subset of all bitmasks, so + // this will never be skipped by the check above. + lane: NoLane, + revertLane: NoLane, + action: update.action, + hasEagerState: update.hasEagerState, + eagerState: update.eagerState, + next: null + }; + newBaseQueueLast = newBaseQueueLast.next = _clone; + } + } else { + // This is an optimistic update. If the "revert" priority is + // sufficient, don't apply the update. Otherwise, apply the update, + // but leave it in the queue so it can be either reverted or + // rebased in a subsequent render. + if (isSubsetOfLanes(renderLanes, revertLane)) { + // The transition that this optimistic update is associated with + // has finished. Pretend the update doesn't exist by skipping + // over it. + update = update.next; + continue; + } else { + var _clone2 = { + // Once we commit an optimistic update, we shouldn't uncommit it + // until the transition it is associated with has finished + // (represented by revertLane). Using NoLane here works because 0 + // is a subset of all bitmasks, so this will never be skipped by + // the check above. + lane: NoLane, + // Reuse the same revertLane so we know when the transition + // has finished. + revertLane: update.revertLane, + action: update.action, + hasEagerState: update.hasEagerState, + eagerState: update.eagerState, + next: null + }; + + if (newBaseQueueLast === null) { + newBaseQueueFirst = newBaseQueueLast = _clone2; + newBaseState = newState; + } else { + newBaseQueueLast = newBaseQueueLast.next = _clone2; + } // Update the remaining priority in the queue. + // TODO: Don't need to accumulate this. Instead, we can remove + // renderLanes from the original lanes. + + currentlyRenderingFiber$1.lanes = mergeLanes( + currentlyRenderingFiber$1.lanes, + revertLane + ); + markSkippedUpdateLanes(revertLane); + } + } // Process this update. + + var action = update.action; + + if (shouldDoubleInvokeUserFnsInHooksDEV) { + reducer(newState, action); + } + + if (update.hasEagerState) { + // If this update is a state update (not a reducer) and was processed eagerly, + // we can use the eagerly computed state + newState = update.eagerState; + } else { + newState = reducer(newState, action); + } + } + + update = update.next; + } while (update !== null && update !== first); + + if (newBaseQueueLast === null) { + newBaseState = newState; + } else { + newBaseQueueLast.next = newBaseQueueFirst; + } // Mark that the fiber performed work, but only if the new state is + // different from the current state. + + if (!objectIs(newState, hook.memoizedState)) { + markWorkInProgressReceivedUpdate(); + } + + hook.memoizedState = newState; + hook.baseState = newBaseState; + hook.baseQueue = newBaseQueueLast; + queue.lastRenderedState = newState; + } + + if (baseQueue === null) { + // `queue.lanes` is used for entangling transitions. We can set it back to + // zero once the queue is empty. + queue.lanes = NoLanes; + } + + var dispatch = queue.dispatch; + return [hook.memoizedState, dispatch]; + } + + function rerenderReducer(reducer, initialArg, init) { + var hook = updateWorkInProgressHook(); + var queue = hook.queue; + + if (queue === null) { + throw new Error( + "Should have a queue. This is likely a bug in React. Please file an issue." + ); + } + + queue.lastRenderedReducer = reducer; // This is a re-render. Apply the new render phase updates to the previous + // work-in-progress hook. + + var dispatch = queue.dispatch; + var lastRenderPhaseUpdate = queue.pending; + var newState = hook.memoizedState; + + if (lastRenderPhaseUpdate !== null) { + // The queue doesn't persist past this render pass. + queue.pending = null; + var firstRenderPhaseUpdate = lastRenderPhaseUpdate.next; + var update = firstRenderPhaseUpdate; + + do { + // Process this render phase update. We don't have to check the + // priority because it will always be the same as the current + // render's. + var action = update.action; + newState = reducer(newState, action); + update = update.next; + } while (update !== firstRenderPhaseUpdate); // Mark that the fiber performed work, but only if the new state is + // different from the current state. + + if (!objectIs(newState, hook.memoizedState)) { + markWorkInProgressReceivedUpdate(); + } + + hook.memoizedState = newState; // Don't persist the state accumulated from the render phase updates to + // the base state unless the queue is empty. + // TODO: Not sure if this is the desired semantics, but it's what we + // do for gDSFP. I can't remember why. + + if (hook.baseQueue === null) { + hook.baseState = newState; + } + + queue.lastRenderedState = newState; + } + + return [newState, dispatch]; + } + + function mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { + var fiber = currentlyRenderingFiber$1; + var hook = mountWorkInProgressHook(); + var nextSnapshot; + + { + nextSnapshot = getSnapshot(); + + { + if (!didWarnUncachedGetSnapshot) { + var cachedSnapshot = getSnapshot(); + + if (!objectIs(nextSnapshot, cachedSnapshot)) { + error( + "The result of getSnapshot should be cached to avoid an infinite loop" + ); + + didWarnUncachedGetSnapshot = true; + } + } + } // Unless we're rendering a blocking lane, schedule a consistency check. + // Right before committing, we will walk the tree and check if any of the + // stores were mutated. + // + // We won't do this if we're hydrating server-rendered content, because if + // the content is stale, it's already visible anyway. Instead we'll patch + // it up in a passive effect. + + var root = getWorkInProgressRoot(); + + if (root === null) { + throw new Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + } + + var rootRenderLanes = getWorkInProgressRootRenderLanes(); + + if (!includesBlockingLane(root, rootRenderLanes)) { + pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); + } + } // Read the current snapshot from the store on every render. This breaks the + // normal rules of React, and only works because store updates are + // always synchronous. + + hook.memoizedState = nextSnapshot; + var inst = { + value: nextSnapshot, + getSnapshot: getSnapshot + }; + hook.queue = inst; // Schedule an effect to subscribe to the store. + + mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [ + subscribe + ]); // Schedule an effect to update the mutable instance fields. We will update + // this whenever subscribe, getSnapshot, or value changes. Because there's no + // clean-up function, and we track the deps correctly, we can call pushEffect + // directly, without storing any additional state. For the same reason, we + // don't need to set a static flag, either. + + fiber.flags |= Passive$1; + pushEffect( + HasEffect | Passive, + updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), + createEffectInstance(), + null + ); + return nextSnapshot; + } + + function updateSyncExternalStore( + subscribe, + getSnapshot, + getServerSnapshot + ) { + var fiber = currentlyRenderingFiber$1; + var hook = updateWorkInProgressHook(); // Read the current snapshot from the store on every render. This breaks the + // normal rules of React, and only works because store updates are + // always synchronous. + + var nextSnapshot; + + { + nextSnapshot = getSnapshot(); + + { + if (!didWarnUncachedGetSnapshot) { + var cachedSnapshot = getSnapshot(); + + if (!objectIs(nextSnapshot, cachedSnapshot)) { + error( + "The result of getSnapshot should be cached to avoid an infinite loop" + ); + + didWarnUncachedGetSnapshot = true; + } + } + } + } + + var prevSnapshot = (currentHook || hook).memoizedState; + var snapshotChanged = !objectIs(prevSnapshot, nextSnapshot); + + if (snapshotChanged) { + hook.memoizedState = nextSnapshot; + markWorkInProgressReceivedUpdate(); + } + + var inst = hook.queue; + updateEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [ + subscribe + ]); // Whenever getSnapshot or subscribe changes, we need to check in the + // commit phase if there was an interleaved mutation. In concurrent mode + // this can happen all the time, but even in synchronous mode, an earlier + // effect may have mutated the store. + + if ( + inst.getSnapshot !== getSnapshot || + snapshotChanged || // Check if the subscribe function changed. We can save some memory by + // checking whether we scheduled a subscription effect above. + (workInProgressHook !== null && + workInProgressHook.memoizedState.tag & HasEffect) + ) { + fiber.flags |= Passive$1; + pushEffect( + HasEffect | Passive, + updateStoreInstance.bind( + null, + fiber, + inst, + nextSnapshot, + getSnapshot + ), + createEffectInstance(), + null + ); // Unless we're rendering a blocking lane, schedule a consistency check. + // Right before committing, we will walk the tree and check if any of the + // stores were mutated. + + var root = getWorkInProgressRoot(); + + if (root === null) { + throw new Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + } + + if (!includesBlockingLane(root, renderLanes)) { + pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); + } + } + + return nextSnapshot; + } + + function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) { + fiber.flags |= StoreConsistency; + var check = { + getSnapshot: getSnapshot, + value: renderedSnapshot + }; + var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; + + if (componentUpdateQueue === null) { + componentUpdateQueue = createFunctionComponentUpdateQueue(); + currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; + componentUpdateQueue.stores = [check]; + } else { + var stores = componentUpdateQueue.stores; + + if (stores === null) { + componentUpdateQueue.stores = [check]; + } else { + stores.push(check); + } + } + } + + function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) { + // These are updated in the passive phase + inst.value = nextSnapshot; + inst.getSnapshot = getSnapshot; // Something may have been mutated in between render and commit. This could + // have been in an event that fired before the passive effects, or it could + // have been in a layout effect. In that case, we would have used the old + // snapsho and getSnapshot values to bail out. We need to check one more time. + + if (checkIfSnapshotChanged(inst)) { + // Force a re-render. + forceStoreRerender(fiber); + } + } + + function subscribeToStore(fiber, inst, subscribe) { + var handleStoreChange = function () { + // The store changed. Check if the snapshot changed since the last time we + // read from the store. + if (checkIfSnapshotChanged(inst)) { + // Force a re-render. + forceStoreRerender(fiber); + } + }; // Subscribe to the store and return a clean-up function. + + return subscribe(handleStoreChange); + } + + function checkIfSnapshotChanged(inst) { + var latestGetSnapshot = inst.getSnapshot; + var prevValue = inst.value; + + try { + var nextValue = latestGetSnapshot(); + return !objectIs(prevValue, nextValue); + } catch (error) { + return true; + } + } + + function forceStoreRerender(fiber) { + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + } + + function mountStateImpl(initialState) { + var hook = mountWorkInProgressHook(); + + if (typeof initialState === "function") { + // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types + initialState = initialState(); + } + + hook.memoizedState = hook.baseState = initialState; + var queue = { + pending: null, + lanes: NoLanes, + dispatch: null, + lastRenderedReducer: basicStateReducer, + lastRenderedState: initialState + }; + hook.queue = queue; + return hook; + } + + function mountState(initialState) { + var hook = mountStateImpl(initialState); + var queue = hook.queue; + var dispatch = dispatchSetState.bind( + null, + currentlyRenderingFiber$1, + queue + ); + queue.dispatch = dispatch; + return [hook.memoizedState, dispatch]; + } + + function updateState(initialState) { + return updateReducer(basicStateReducer); + } + + function rerenderState(initialState) { + return rerenderReducer(basicStateReducer); + } + + function mountOptimistic(passthrough, reducer) { + var hook = mountWorkInProgressHook(); + hook.memoizedState = hook.baseState = passthrough; + var queue = { + pending: null, + lanes: NoLanes, + dispatch: null, + // Optimistic state does not use the eager update optimization. + lastRenderedReducer: null, + lastRenderedState: null + }; + hook.queue = queue; // This is different than the normal setState function. + + var dispatch = dispatchOptimisticSetState.bind( + null, + currentlyRenderingFiber$1, + true, + queue + ); + queue.dispatch = dispatch; + return [passthrough, dispatch]; + } + + function updateOptimistic(passthrough, reducer) { + var hook = updateWorkInProgressHook(); + return updateOptimisticImpl(hook, currentHook, passthrough, reducer); + } + + function updateOptimisticImpl(hook, current, passthrough, reducer) { + // Optimistic updates are always rebased on top of the latest value passed in + // as an argument. It's called a passthrough because if there are no pending + // updates, it will be returned as-is. + // + // Reset the base state to the passthrough. Future updates will be applied + // on top of this. + hook.baseState = passthrough; // If a reducer is not provided, default to the same one used by useState. + + var resolvedReducer = + typeof reducer === "function" ? reducer : basicStateReducer; + return updateReducerImpl(hook, currentHook, resolvedReducer); + } + + function rerenderOptimistic(passthrough, reducer) { + // Unlike useState, useOptimistic doesn't support render phase updates. + // Also unlike useState, we need to replay all pending updates again in case + // the passthrough value changed. + // + // So instead of a forked re-render implementation that knows how to handle + // render phase udpates, we can use the same implementation as during a + // regular mount or update. + var hook = updateWorkInProgressHook(); + + if (currentHook !== null) { + // This is an update. Process the update queue. + return updateOptimisticImpl(hook, currentHook, passthrough, reducer); + } // This is a mount. No updates to process. + // Reset the base state to the passthrough. Future updates will be applied + // on top of this. + + hook.baseState = passthrough; + var dispatch = hook.queue.dispatch; + return [passthrough, dispatch]; + } // useFormState actions run sequentially, because each action receives the + + function pushEffect(tag, create, inst, deps) { + var effect = { + tag: tag, + create: create, + inst: inst, + deps: deps, + // Circular + next: null + }; + var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; + + if (componentUpdateQueue === null) { + componentUpdateQueue = createFunctionComponentUpdateQueue(); + currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; + componentUpdateQueue.lastEffect = effect.next = effect; + } else { + var lastEffect = componentUpdateQueue.lastEffect; + + if (lastEffect === null) { + componentUpdateQueue.lastEffect = effect.next = effect; + } else { + var firstEffect = lastEffect.next; + lastEffect.next = effect; + effect.next = firstEffect; + componentUpdateQueue.lastEffect = effect; + } + } + + return effect; + } + + function createEffectInstance() { + return { + destroy: undefined + }; + } + + var stackContainsErrorMessage = null; + + function getCallerStackFrame() { + // eslint-disable-next-line react-internal/prod-error-codes + var stackFrames = new Error("Error message").stack.split("\n"); // Some browsers (e.g. Chrome) include the error message in the stack + // but others (e.g. Firefox) do not. + + if (stackContainsErrorMessage === null) { + stackContainsErrorMessage = stackFrames[0].includes("Error message"); + } + + return stackContainsErrorMessage + ? stackFrames.slice(3, 4).join("\n") + : stackFrames.slice(2, 3).join("\n"); + } + + function mountRef(initialValue) { + var hook = mountWorkInProgressHook(); + + if (enableUseRefAccessWarning) { + { + // Support lazy initialization pattern shown in docs. + // We need to store the caller stack frame so that we don't warn on subsequent renders. + var hasBeenInitialized = initialValue != null; + var lazyInitGetterStack = null; + var didCheckForLazyInit = false; // Only warn once per component+hook. + + var didWarnAboutRead = false; + var didWarnAboutWrite = false; + var current = initialValue; + var ref = { + get current() { + if (!hasBeenInitialized) { + didCheckForLazyInit = true; + lazyInitGetterStack = getCallerStackFrame(); + } else if ( + currentlyRenderingFiber$1 !== null && + !didWarnAboutRead + ) { + if ( + lazyInitGetterStack === null || + lazyInitGetterStack !== getCallerStackFrame() + ) { + didWarnAboutRead = true; + + warn( + "%s: Unsafe read of a mutable value during render.\n\n" + + "Reading from a ref during render is only safe if:\n" + + "1. The ref value has not been updated, or\n" + + "2. The ref holds a lazily-initialized value that is only set once.\n", + getComponentNameFromFiber(currentlyRenderingFiber$1) || + "Unknown" + ); + } + } + + return current; + }, + + set current(value) { + if (currentlyRenderingFiber$1 !== null && !didWarnAboutWrite) { + if (hasBeenInitialized || !didCheckForLazyInit) { + didWarnAboutWrite = true; + + warn( + "%s: Unsafe write of a mutable value during render.\n\n" + + "Writing to a ref during render is only safe if the ref holds " + + "a lazily-initialized value that is only set once.\n", + getComponentNameFromFiber(currentlyRenderingFiber$1) || + "Unknown" + ); + } + } + + hasBeenInitialized = true; + current = value; + } + }; + Object.seal(ref); + hook.memoizedState = ref; + return ref; + } + } else { + var _ref2 = { + current: initialValue + }; + hook.memoizedState = _ref2; + return _ref2; + } + } + + function updateRef(initialValue) { + var hook = updateWorkInProgressHook(); + return hook.memoizedState; + } + + function mountEffectImpl(fiberFlags, hookFlags, create, deps) { + var hook = mountWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + currentlyRenderingFiber$1.flags |= fiberFlags; + hook.memoizedState = pushEffect( + HasEffect | hookFlags, + create, + createEffectInstance(), + nextDeps + ); + } + + function updateEffectImpl(fiberFlags, hookFlags, create, deps) { + var hook = updateWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var effect = hook.memoizedState; + var inst = effect.inst; // currentHook is null on initial mount when rerendering after a render phase + // state update or for strict mode. + + if (currentHook !== null) { + if (nextDeps !== null) { + var prevEffect = currentHook.memoizedState; + var prevDeps = prevEffect.deps; + + if (areHookInputsEqual(nextDeps, prevDeps)) { + hook.memoizedState = pushEffect(hookFlags, create, inst, nextDeps); + return; + } + } + } + + currentlyRenderingFiber$1.flags |= fiberFlags; + hook.memoizedState = pushEffect( + HasEffect | hookFlags, + create, + inst, + nextDeps + ); + } + + function mountEffect(create, deps) { + if ( + (currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode && + (currentlyRenderingFiber$1.mode & NoStrictPassiveEffectsMode) === NoMode + ) { + mountEffectImpl( + MountPassiveDev | Passive$1 | PassiveStatic, + Passive, + create, + deps + ); + } else { + mountEffectImpl(Passive$1 | PassiveStatic, Passive, create, deps); + } + } + + function updateEffect(create, deps) { + updateEffectImpl(Passive$1, Passive, create, deps); + } + + function useEffectEventImpl(payload) { + currentlyRenderingFiber$1.flags |= Update; + var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; + + if (componentUpdateQueue === null) { + componentUpdateQueue = createFunctionComponentUpdateQueue(); + currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; + componentUpdateQueue.events = [payload]; + } else { + var events = componentUpdateQueue.events; + + if (events === null) { + componentUpdateQueue.events = [payload]; + } else { + events.push(payload); + } + } + } + + function mountEvent(callback) { + var hook = mountWorkInProgressHook(); + var ref = { + impl: callback + }; + hook.memoizedState = ref; // $FlowIgnore[incompatible-return] + + return function eventFn() { + if (isInvalidExecutionContextForEventFunction()) { + throw new Error( + "A function wrapped in useEffectEvent can't be called during rendering." + ); + } + + return ref.impl.apply(undefined, arguments); + }; + } + + function updateEvent(callback) { + var hook = updateWorkInProgressHook(); + var ref = hook.memoizedState; + useEffectEventImpl({ + ref: ref, + nextImpl: callback + }); // $FlowIgnore[incompatible-return] + + return function eventFn() { + if (isInvalidExecutionContextForEventFunction()) { + throw new Error( + "A function wrapped in useEffectEvent can't be called during rendering." + ); + } + + return ref.impl.apply(undefined, arguments); + }; + } + + function mountInsertionEffect(create, deps) { + mountEffectImpl(Update, Insertion, create, deps); + } + + function updateInsertionEffect(create, deps) { + return updateEffectImpl(Update, Insertion, create, deps); + } + + function mountLayoutEffect(create, deps) { + var fiberFlags = Update | LayoutStatic; + + if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { + fiberFlags |= MountLayoutDev; + } + + return mountEffectImpl(fiberFlags, Layout, create, deps); + } + + function updateLayoutEffect(create, deps) { + return updateEffectImpl(Update, Layout, create, deps); + } + + function imperativeHandleEffect(create, ref) { + if (typeof ref === "function") { + var refCallback = ref; + var inst = create(); + refCallback(inst); + return function () { + refCallback(null); + }; + } else if (ref !== null && ref !== undefined) { + var refObject = ref; + + { + if (!refObject.hasOwnProperty("current")) { + 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(", ") + "}" + ); + } + } + + var _inst = create(); + + refObject.current = _inst; + return function () { + refObject.current = null; + }; + } + } + + function mountImperativeHandle(ref, create, deps) { + { + if (typeof create !== "function") { + error( + "Expected useImperativeHandle() second argument to be a function " + + "that creates a handle. Instead received: %s.", + create !== null ? typeof create : "null" + ); + } + } // TODO: If deps are provided, should we skip comparing the ref itself? + + var effectDeps = + deps !== null && deps !== undefined ? deps.concat([ref]) : null; + var fiberFlags = Update | LayoutStatic; + + if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { + fiberFlags |= MountLayoutDev; + } + + mountEffectImpl( + fiberFlags, + Layout, + imperativeHandleEffect.bind(null, create, ref), + effectDeps + ); + } + + function updateImperativeHandle(ref, create, deps) { + { + if (typeof create !== "function") { + error( + "Expected useImperativeHandle() second argument to be a function " + + "that creates a handle. Instead received: %s.", + create !== null ? typeof create : "null" + ); + } + } // TODO: If deps are provided, should we skip comparing the ref itself? + + var effectDeps = + deps !== null && deps !== undefined ? deps.concat([ref]) : null; + updateEffectImpl( + Update, + Layout, + imperativeHandleEffect.bind(null, create, ref), + effectDeps + ); + } + + function mountDebugValue(value, formatterFn) { + // This hook is normally a no-op. + // The react-debug-hooks package injects its own implementation + // so that e.g. DevTools can display custom hook values. + } + + var updateDebugValue = mountDebugValue; + + function mountCallback(callback, deps) { + var hook = mountWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + hook.memoizedState = [callback, nextDeps]; + return callback; + } + + function updateCallback(callback, deps) { + var hook = updateWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var prevState = hook.memoizedState; + + if (nextDeps !== null) { + var prevDeps = prevState[1]; + + if (areHookInputsEqual(nextDeps, prevDeps)) { + return prevState[0]; + } + } + + hook.memoizedState = [callback, nextDeps]; + return callback; + } + + function mountMemo(nextCreate, deps) { + var hook = mountWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + + if (shouldDoubleInvokeUserFnsInHooksDEV) { + nextCreate(); + } + + var nextValue = nextCreate(); + hook.memoizedState = [nextValue, nextDeps]; + return nextValue; + } + + function updateMemo(nextCreate, deps) { + var hook = updateWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var prevState = hook.memoizedState; // Assume these are defined. If they're not, areHookInputsEqual will warn. + + if (nextDeps !== null) { + var prevDeps = prevState[1]; + + if (areHookInputsEqual(nextDeps, prevDeps)) { + return prevState[0]; + } + } + + if (shouldDoubleInvokeUserFnsInHooksDEV) { + nextCreate(); + } + + var nextValue = nextCreate(); + hook.memoizedState = [nextValue, nextDeps]; + return nextValue; + } + + function mountDeferredValue(value, initialValue) { + var hook = mountWorkInProgressHook(); + return mountDeferredValueImpl(hook, value, initialValue); + } + + function updateDeferredValue(value, initialValue) { + var hook = updateWorkInProgressHook(); + var resolvedCurrentHook = currentHook; + var prevValue = resolvedCurrentHook.memoizedState; + return updateDeferredValueImpl(hook, prevValue, value, initialValue); + } + + function rerenderDeferredValue(value, initialValue) { + var hook = updateWorkInProgressHook(); + + if (currentHook === null) { + // This is a rerender during a mount. + return mountDeferredValueImpl(hook, value, initialValue); + } else { + // This is a rerender during an update. + var prevValue = currentHook.memoizedState; + return updateDeferredValueImpl(hook, prevValue, value, initialValue); + } + } + + function mountDeferredValueImpl(hook, value, initialValue) { + if ( + enableUseDeferredValueInitialArg && // When `initialValue` is provided, we defer the initial render even if the + // current render is not synchronous. + initialValue !== undefined && // However, to avoid waterfalls, we do not defer if this render + // was itself spawned by an earlier useDeferredValue. Check if DeferredLane + // is part of the render lanes. + !includesSomeLane(renderLanes, DeferredLane) + ) { + // Render with the initial value + hook.memoizedState = initialValue; // Schedule a deferred render to switch to the final value. + + var deferredLane = requestDeferredLane(); + currentlyRenderingFiber$1.lanes = mergeLanes( + currentlyRenderingFiber$1.lanes, + deferredLane + ); + markSkippedUpdateLanes(deferredLane); + return initialValue; + } else { + hook.memoizedState = value; + return value; + } + } + + function updateDeferredValueImpl(hook, prevValue, value, initialValue) { + if (objectIs(value, prevValue)) { + // The incoming value is referentially identical to the currently rendered + // value, so we can bail out quickly. + return value; + } else { + // Received a new value that's different from the current value. + // Check if we're inside a hidden tree + if (isCurrentTreeHidden()) { + // Revealing a prerendered tree is considered the same as mounting new + // one, so we reuse the "mount" path in this case. + var resultValue = mountDeferredValueImpl(hook, value, initialValue); // Unlike during an actual mount, we need to mark this as an update if + // the value changed. + + if (!objectIs(resultValue, prevValue)) { + markWorkInProgressReceivedUpdate(); + } + + return resultValue; + } + + var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes); + + if (shouldDeferValue) { + // This is an urgent update. Since the value has changed, keep using the + // previous value and spawn a deferred render to update it later. + // Schedule a deferred render + var deferredLane = requestDeferredLane(); + currentlyRenderingFiber$1.lanes = mergeLanes( + currentlyRenderingFiber$1.lanes, + deferredLane + ); + markSkippedUpdateLanes(deferredLane); // Reuse the previous value. We do not need to mark this as an update, + // because we did not render a new value. + + return prevValue; + } else { + // This is not an urgent update, so we can use the latest value regardless + // of what it is. No need to defer it. + // Mark this as an update to prevent the fiber from bailing out. + markWorkInProgressReceivedUpdate(); + hook.memoizedState = value; + return value; + } + } + } + + function startTransition( + fiber, + queue, + pendingState, + finishedState, + callback, + options + ) { + var previousPriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority( + higherEventPriority(previousPriority, ContinuousEventPriority) + ); + var prevTransition = ReactCurrentBatchConfig$2.transition; + var currentTransition = {}; + + if (enableAsyncActions) { + // We don't really need to use an optimistic update here, because we + // schedule a second "revert" update below (which we use to suspend the + // transition until the async action scope has finished). But we'll use an + // optimistic update anyway to make it less likely the behavior accidentally + // diverges; for example, both an optimistic update and this one should + // share the same lane. + ReactCurrentBatchConfig$2.transition = currentTransition; + dispatchOptimisticSetState(fiber, false, queue, pendingState); + } else { + ReactCurrentBatchConfig$2.transition = null; + dispatchSetState(fiber, queue, pendingState); + ReactCurrentBatchConfig$2.transition = currentTransition; + } + + if (enableTransitionTracing) { + if (options !== undefined && options.name !== undefined) { + ReactCurrentBatchConfig$2.transition.name = options.name; + ReactCurrentBatchConfig$2.transition.startTime = now$1(); + } + } + + { + ReactCurrentBatchConfig$2.transition._updatedFibers = new Set(); + } + + try { + if (enableAsyncActions) { + var returnValue = callback(); // Check if we're inside an async action scope. If so, we'll entangle + // this new action with the existing scope. + // + // If we're not already inside an async action scope, and this action is + // async, then we'll create a new async scope. + // + // In the async case, the resulting render will suspend until the async + // action scope has finished. + + if ( + returnValue !== null && + typeof returnValue === "object" && + typeof returnValue.then === "function" + ) { + var thenable = returnValue; // This is a thenable that resolves to `finishedState` once the async + // action scope has finished. + + var entangledResult = requestAsyncActionContext( + thenable, + finishedState + ); + dispatchSetState(fiber, queue, entangledResult); + } else { + // This is either `finishedState` or a thenable that resolves to + // `finishedState`, depending on whether we're inside an async + // action scope. + var _entangledResult2 = requestSyncActionContext( + returnValue, + finishedState + ); + + dispatchSetState(fiber, queue, _entangledResult2); + } + } else { + // Async actions are not enabled. + dispatchSetState(fiber, queue, finishedState); + callback(); + } + } catch (error) { + if (enableAsyncActions) { + // This is a trick to get the `useTransition` hook to rethrow the error. + // When it unwraps the thenable with the `use` algorithm, the error + // will be thrown. + var rejectedThenable = { + then: function () {}, + status: "rejected", + reason: error + }; + dispatchSetState(fiber, queue, rejectedThenable); + } else { + // The error rethrowing behavior is only enabled when the async actions + // feature is on, even for sync actions. + throw error; + } + } finally { + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig$2.transition = prevTransition; + + { + if (prevTransition === null && currentTransition._updatedFibers) { + var updatedFibersCount = currentTransition._updatedFibers.size; + + currentTransition._updatedFibers.clear(); + + if (updatedFibersCount > 10) { + 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." + ); + } + } + } + } + } + + function mountTransition() { + var stateHook = mountStateImpl(false); // The `start` method never changes. + + var start = startTransition.bind( + null, + currentlyRenderingFiber$1, + stateHook.queue, + true, + false + ); + var hook = mountWorkInProgressHook(); + hook.memoizedState = start; + return [false, start]; + } + + function updateTransition() { + var _updateState = updateState(), + booleanOrThenable = _updateState[0]; + + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; + var isPending = + typeof booleanOrThenable === "boolean" + ? booleanOrThenable // This will suspend until the async action scope has finished. + : useThenable(booleanOrThenable); + return [isPending, start]; + } + + function rerenderTransition() { + var _rerenderState = rerenderState(), + booleanOrThenable = _rerenderState[0]; + + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; + var isPending = + typeof booleanOrThenable === "boolean" + ? booleanOrThenable // This will suspend until the async action scope has finished. + : useThenable(booleanOrThenable); + return [isPending, start]; + } + + function mountId() { + var hook = mountWorkInProgressHook(); + var root = getWorkInProgressRoot(); // TODO: In Fizz, id generation is specific to each server config. Maybe we + // should do this in Fiber, too? Deferring this decision for now because + // there's no other place to store the prefix except for an internal field on + // the public createRoot object, which the fiber tree does not currently have + // a reference to. + + var identifierPrefix = root.identifierPrefix; + var id; + + { + // Use a lowercase r prefix for client-generated ids. + var globalClientId = globalClientIdCounter++; + id = ":" + identifierPrefix + "r" + globalClientId.toString(32) + ":"; + } + + hook.memoizedState = id; + return id; + } + + function updateId() { + var hook = updateWorkInProgressHook(); + var id = hook.memoizedState; + return id; + } + + function mountRefresh() { + var hook = mountWorkInProgressHook(); + var refresh = (hook.memoizedState = refreshCache.bind( + null, + currentlyRenderingFiber$1 + )); + return refresh; + } + + function updateRefresh() { + var hook = updateWorkInProgressHook(); + return hook.memoizedState; + } + + function refreshCache(fiber, seedKey, seedValue) { + // TODO: Consider warning if the refresh is at discrete priority, or if we + // otherwise suspect that it wasn't batched properly. + + var provider = fiber.return; + + while (provider !== null) { + switch (provider.tag) { + case CacheComponent: + case HostRoot: { + // Schedule an update on the cache boundary to trigger a refresh. + var lane = requestUpdateLane(provider); + var refreshUpdate = createUpdate(lane); + var root = enqueueUpdate(provider, refreshUpdate, lane); + + if (root !== null) { + scheduleUpdateOnFiber(root, provider, lane); + entangleTransitions(root, provider, lane); + } // TODO: If a refresh never commits, the new cache created here must be + // released. A simple case is start refreshing a cache boundary, but then + // unmount that boundary before the refresh completes. + + var seededCache = createCache(); + + if (seedKey !== null && seedKey !== undefined && root !== null) { + { + // Seed the cache with the value passed by the caller. This could be + // from a server mutation, or it could be a streaming response. + seededCache.data.set(seedKey, seedValue); + } + } + + var payload = { + cache: seededCache + }; + refreshUpdate.payload = payload; + return; + } + } + + provider = provider.return; + } // TODO: Warn if unmounted? + } + + function dispatchReducerAction(fiber, queue, action) { + { + if (typeof arguments[3] === "function") { + 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()." + ); + } + } + + var lane = requestUpdateLane(fiber); + var update = { + lane: lane, + revertLane: NoLane, + action: action, + hasEagerState: false, + eagerState: null, + next: null + }; + + if (isRenderPhaseUpdate(fiber)) { + enqueueRenderPhaseUpdate(queue, update); + } else { + var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); + + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane); + entangleTransitionUpdate(root, queue, lane); + } + } + + markUpdateInDevTools(fiber, lane, action); + } + + function dispatchSetState(fiber, queue, action) { + { + if (typeof arguments[3] === "function") { + 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()." + ); + } + } + + var lane = requestUpdateLane(fiber); + var update = { + lane: lane, + revertLane: NoLane, + action: action, + hasEagerState: false, + eagerState: null, + next: null + }; + + if (isRenderPhaseUpdate(fiber)) { + enqueueRenderPhaseUpdate(queue, update); + } else { + var alternate = fiber.alternate; + + if ( + fiber.lanes === NoLanes && + (alternate === null || alternate.lanes === NoLanes) + ) { + // The queue is currently empty, which means we can eagerly compute the + // next state before entering the render phase. If the new state is the + // same as the current state, we may be able to bail out entirely. + var lastRenderedReducer = queue.lastRenderedReducer; + + if (lastRenderedReducer !== null) { + var prevDispatcher; + + { + prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + } + + try { + var currentState = queue.lastRenderedState; + var eagerState = lastRenderedReducer(currentState, action); // Stash the eagerly computed state, and the reducer used to compute + // it, on the update object. If the reducer hasn't changed by the + // time we enter the render phase, then the eager state can be used + // without calling the reducer again. + + update.hasEagerState = true; + update.eagerState = eagerState; + + if (objectIs(eagerState, currentState)) { + // Fast path. We can bail out without scheduling React to re-render. + // It's still possible that we'll need to rebase this update later, + // if the component re-renders for a different reason and by that + // time the reducer has changed. + // TODO: Do we still need to entangle transitions in this case? + enqueueConcurrentHookUpdateAndEagerlyBailout( + fiber, + queue, + update + ); + return; + } + } catch (error) { + // Suppress the error. It will throw again in the render phase. + } finally { + { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + } + } + } + + var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); + + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane); + entangleTransitionUpdate(root, queue, lane); + } + } + + markUpdateInDevTools(fiber, lane, action); + } + + function dispatchOptimisticSetState( + fiber, + throwIfDuringRender, + queue, + action + ) { + { + if (ReactCurrentBatchConfig$2.transition === null) { + // An optimistic update occurred, but startTransition is not on the stack. + // There are two likely scenarios. + // One possibility is that the optimistic update is triggered by a regular + // event handler (e.g. `onSubmit`) instead of an action. This is a mistake + // and we will warn. + // The other possibility is the optimistic update is inside an async + // action, but after an `await`. In this case, we can make it "just work" + // by associating the optimistic update with the pending async action. + // Technically it's possible that the optimistic update is unrelated to + // the pending action, but we don't have a way of knowing this for sure + // because browsers currently do not provide a way to track async scope. + // (The AsyncContext proposal, if it lands, will solve this in the + // future.) However, this is no different than the problem of unrelated + // transitions being grouped together — it's not wrong per se, but it's + // not ideal. + // Once AsyncContext starts landing in browsers, we will provide better + // warnings in development for these cases. + if (peekEntangledActionLane() !== NoLane); + else { + // There's no pending async action. The most likely cause is that we're + // inside a regular event handler (e.g. onSubmit) instead of an action. + error( + "An optimistic state update occurred outside a transition or " + + "action. To fix, move the update to an action, or wrap " + + "with startTransition." + ); + } + } + } + + var update = { + // An optimistic update commits synchronously. + lane: SyncLane, + // After committing, the optimistic update is "reverted" using the same + // lane as the transition it's associated with. + revertLane: requestTransitionLane(), + action: action, + hasEagerState: false, + eagerState: null, + next: null + }; + + if (isRenderPhaseUpdate(fiber)) { + // When calling startTransition during render, this warns instead of + // throwing because throwing would be a breaking change. setOptimisticState + // is a new API so it's OK to throw. + if (throwIfDuringRender) { + throw new Error("Cannot update optimistic state while rendering."); + } else { + // startTransition was called during render. We don't need to do anything + // besides warn here because the render phase update would be overidden by + // the second update, anyway. We can remove this branch and make it throw + // in a future release. + { + error("Cannot call startTransition while rendering."); + } + } + } else { + var root = enqueueConcurrentHookUpdate(fiber, queue, update, SyncLane); + + if (root !== null) { + // NOTE: The optimistic update implementation assumes that the transition + // will never be attempted before the optimistic update. This currently + // holds because the optimistic update is always synchronous. If we ever + // change that, we'll need to account for this. + scheduleUpdateOnFiber(root, fiber, SyncLane); // Optimistic updates are always synchronous, so we don't need to call + // entangleTransitionUpdate here. + } + } + + markUpdateInDevTools(fiber, SyncLane, action); + } + + function isRenderPhaseUpdate(fiber) { + var alternate = fiber.alternate; + return ( + fiber === currentlyRenderingFiber$1 || + (alternate !== null && alternate === currentlyRenderingFiber$1) + ); + } + + function enqueueRenderPhaseUpdate(queue, update) { + // This is a render phase update. Stash it in a lazily-created map of + // queue -> linked list of updates. After this render pass, we'll restart + // and apply the stashed updates on top of the work-in-progress hook. + didScheduleRenderPhaseUpdateDuringThisPass = + didScheduleRenderPhaseUpdate = true; + var pending = queue.pending; + + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; + } + + queue.pending = update; + } // TODO: Move to ReactFiberConcurrentUpdates? + + function entangleTransitionUpdate(root, queue, lane) { + if (isTransitionLane(lane)) { + var queueLanes = queue.lanes; // If any entangled lanes are no longer pending on the root, then they + // must have finished. We can remove them from the shared queue, which + // represents a superset of the actually pending lanes. In some cases we + // may entangle more than we need to, but that's OK. In fact it's worse if + // we *don't* entangle when we should. + + queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. + + var newQueueLanes = mergeLanes(queueLanes, lane); + queue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if + // the lane finished since the last time we entangled it. So we need to + // entangle it again, just to be sure. + + markRootEntangled(root, newQueueLanes); + } + } + + function markUpdateInDevTools(fiber, lane, action) { + { + if (enableDebugTracing) { + if (fiber.mode & DebugTracingMode) { + var name = getComponentNameFromFiber(fiber) || "Unknown"; + logStateUpdateScheduled(name, lane, action); + } + } + } + + if (enableSchedulingProfiler) { + markStateUpdateScheduled(fiber, lane); + } + } + + var ContextOnlyDispatcher = { + readContext: readContext, + use: use, + useCallback: throwInvalidHookError, + useContext: throwInvalidHookError, + useEffect: throwInvalidHookError, + useImperativeHandle: throwInvalidHookError, + useInsertionEffect: throwInvalidHookError, + useLayoutEffect: throwInvalidHookError, + useMemo: throwInvalidHookError, + useReducer: throwInvalidHookError, + useRef: throwInvalidHookError, + useState: throwInvalidHookError, + useDebugValue: throwInvalidHookError, + useDeferredValue: throwInvalidHookError, + useTransition: throwInvalidHookError, + useSyncExternalStore: throwInvalidHookError, + useId: throwInvalidHookError + }; + + { + ContextOnlyDispatcher.useCacheRefresh = throwInvalidHookError; + } + + { + ContextOnlyDispatcher.useMemoCache = throwInvalidHookError; + } + + { + ContextOnlyDispatcher.useEffectEvent = throwInvalidHookError; + } + + if (enableAsyncActions) { + ContextOnlyDispatcher.useOptimistic = throwInvalidHookError; + } + + var HooksDispatcherOnMountInDEV = null; + var HooksDispatcherOnMountWithHookTypesInDEV = null; + var HooksDispatcherOnUpdateInDEV = null; + var HooksDispatcherOnRerenderInDEV = null; + var InvalidNestedHooksDispatcherOnMountInDEV = null; + var InvalidNestedHooksDispatcherOnUpdateInDEV = null; + var InvalidNestedHooksDispatcherOnRerenderInDEV = null; + + { + var warnInvalidContextAccess = function () { + 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()." + ); + }; + + var warnInvalidHookAccess = function () { + 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" ); + }; + + HooksDispatcherOnMountInDEV = { + readContext: function (context) { + return readContext(context); + }, + use: use, + useCallback: function (callback, deps) { + currentHookNameInDev = "useCallback"; + mountHookTypesDev(); + checkDepsAreArrayDev(deps); + return mountCallback(callback, deps); + }, + useContext: function (context) { + currentHookNameInDev = "useContext"; + mountHookTypesDev(); + return readContext(context); + }, + useEffect: function (create, deps) { + currentHookNameInDev = "useEffect"; + mountHookTypesDev(); + checkDepsAreArrayDev(deps); + return mountEffect(create, deps); + }, + useImperativeHandle: function (ref, create, deps) { + currentHookNameInDev = "useImperativeHandle"; + mountHookTypesDev(); + checkDepsAreArrayDev(deps); + return mountImperativeHandle(ref, create, deps); + }, + useInsertionEffect: function (create, deps) { + currentHookNameInDev = "useInsertionEffect"; + mountHookTypesDev(); + checkDepsAreArrayDev(deps); + return mountInsertionEffect(create, deps); + }, + useLayoutEffect: function (create, deps) { + currentHookNameInDev = "useLayoutEffect"; + mountHookTypesDev(); + checkDepsAreArrayDev(deps); + return mountLayoutEffect(create, deps); + }, + useMemo: function (create, deps) { + currentHookNameInDev = "useMemo"; + mountHookTypesDev(); + checkDepsAreArrayDev(deps); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountMemo(create, deps); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useReducer: function (reducer, initialArg, init) { + currentHookNameInDev = "useReducer"; + mountHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountReducer(reducer, initialArg, init); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useRef: function (initialValue) { + currentHookNameInDev = "useRef"; + mountHookTypesDev(); + return mountRef(initialValue); + }, + useState: function (initialState) { + currentHookNameInDev = "useState"; + mountHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + mountHookTypesDev(); + return mountDebugValue(); + }, + useDeferredValue: function (value, initialValue) { + currentHookNameInDev = "useDeferredValue"; + mountHookTypesDev(); + return mountDeferredValue(value, initialValue); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + mountHookTypesDev(); + return mountTransition(); + }, + useSyncExternalStore: function ( + subscribe, + getSnapshot, + getServerSnapshot + ) { + currentHookNameInDev = "useSyncExternalStore"; + mountHookTypesDev(); + return mountSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + mountHookTypesDev(); + return mountId(); + } + }; + + { + HooksDispatcherOnMountInDEV.useCacheRefresh = + function useCacheRefresh() { + currentHookNameInDev = "useCacheRefresh"; + mountHookTypesDev(); + return mountRefresh(); + }; + } + + { + HooksDispatcherOnMountInDEV.useMemoCache = useMemoCache; + } + + { + HooksDispatcherOnMountInDEV.useEffectEvent = function useEffectEvent( + callback + ) { + currentHookNameInDev = "useEffectEvent"; + mountHookTypesDev(); + return mountEvent(callback); + }; + } + + if (enableAsyncActions) { + HooksDispatcherOnMountInDEV.useOptimistic = function useOptimistic( + passthrough, + reducer + ) { + currentHookNameInDev = "useOptimistic"; + mountHookTypesDev(); + return mountOptimistic(passthrough); + }; + } + + HooksDispatcherOnMountWithHookTypesInDEV = { + readContext: function (context) { + return readContext(context); + }, + use: use, + useCallback: function (callback, deps) { + currentHookNameInDev = "useCallback"; + updateHookTypesDev(); + return mountCallback(callback, deps); + }, + useContext: function (context) { + currentHookNameInDev = "useContext"; + updateHookTypesDev(); + return readContext(context); + }, + useEffect: function (create, deps) { + currentHookNameInDev = "useEffect"; + updateHookTypesDev(); + return mountEffect(create, deps); + }, + useImperativeHandle: function (ref, create, deps) { + currentHookNameInDev = "useImperativeHandle"; + updateHookTypesDev(); + return mountImperativeHandle(ref, create, deps); + }, + useInsertionEffect: function (create, deps) { + currentHookNameInDev = "useInsertionEffect"; + updateHookTypesDev(); + return mountInsertionEffect(create, deps); + }, + useLayoutEffect: function (create, deps) { + currentHookNameInDev = "useLayoutEffect"; + updateHookTypesDev(); + return mountLayoutEffect(create, deps); + }, + useMemo: function (create, deps) { + currentHookNameInDev = "useMemo"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountMemo(create, deps); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useReducer: function (reducer, initialArg, init) { + currentHookNameInDev = "useReducer"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountReducer(reducer, initialArg, init); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useRef: function (initialValue) { + currentHookNameInDev = "useRef"; + updateHookTypesDev(); + return mountRef(initialValue); + }, + useState: function (initialState) { + currentHookNameInDev = "useState"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + updateHookTypesDev(); + return mountDebugValue(); + }, + useDeferredValue: function (value, initialValue) { + currentHookNameInDev = "useDeferredValue"; + updateHookTypesDev(); + return mountDeferredValue(value, initialValue); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + updateHookTypesDev(); + return mountTransition(); + }, + useSyncExternalStore: function ( + subscribe, + getSnapshot, + getServerSnapshot + ) { + currentHookNameInDev = "useSyncExternalStore"; + updateHookTypesDev(); + return mountSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + updateHookTypesDev(); + return mountId(); + } + }; + + { + HooksDispatcherOnMountWithHookTypesInDEV.useCacheRefresh = + function useCacheRefresh() { + currentHookNameInDev = "useCacheRefresh"; + updateHookTypesDev(); + return mountRefresh(); + }; + } + + { + HooksDispatcherOnMountWithHookTypesInDEV.useMemoCache = useMemoCache; + } + + { + HooksDispatcherOnMountWithHookTypesInDEV.useEffectEvent = + function useEffectEvent(callback) { + currentHookNameInDev = "useEffectEvent"; + updateHookTypesDev(); + return mountEvent(callback); + }; + } + + if (enableAsyncActions) { + HooksDispatcherOnMountWithHookTypesInDEV.useOptimistic = + function useOptimistic(passthrough, reducer) { + currentHookNameInDev = "useOptimistic"; + updateHookTypesDev(); + return mountOptimistic(passthrough); + }; + } + + HooksDispatcherOnUpdateInDEV = { + readContext: function (context) { + return readContext(context); + }, + use: use, + useCallback: function (callback, deps) { + currentHookNameInDev = "useCallback"; + updateHookTypesDev(); + return updateCallback(callback, deps); + }, + useContext: function (context) { + currentHookNameInDev = "useContext"; + updateHookTypesDev(); + return readContext(context); + }, + useEffect: function (create, deps) { + currentHookNameInDev = "useEffect"; + updateHookTypesDev(); + return updateEffect(create, deps); + }, + useImperativeHandle: function (ref, create, deps) { + currentHookNameInDev = "useImperativeHandle"; + updateHookTypesDev(); + return updateImperativeHandle(ref, create, deps); + }, + useInsertionEffect: function (create, deps) { + currentHookNameInDev = "useInsertionEffect"; + updateHookTypesDev(); + return updateInsertionEffect(create, deps); + }, + useLayoutEffect: function (create, deps) { + currentHookNameInDev = "useLayoutEffect"; + updateHookTypesDev(); + return updateLayoutEffect(create, deps); + }, + useMemo: function (create, deps) { + currentHookNameInDev = "useMemo"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return updateMemo(create, deps); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useReducer: function (reducer, initialArg, init) { + currentHookNameInDev = "useReducer"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return updateReducer(reducer, initialArg, init); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useRef: function (initialValue) { + currentHookNameInDev = "useRef"; + updateHookTypesDev(); + return updateRef(); + }, + useState: function (initialState) { + currentHookNameInDev = "useState"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return updateState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + updateHookTypesDev(); + return updateDebugValue(); + }, + useDeferredValue: function (value, initialValue) { + currentHookNameInDev = "useDeferredValue"; + updateHookTypesDev(); + return updateDeferredValue(value, initialValue); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + updateHookTypesDev(); + return updateTransition(); + }, + useSyncExternalStore: function ( + subscribe, + getSnapshot, + getServerSnapshot + ) { + currentHookNameInDev = "useSyncExternalStore"; + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + updateHookTypesDev(); + return updateId(); + } + }; + + { + HooksDispatcherOnUpdateInDEV.useCacheRefresh = + function useCacheRefresh() { + currentHookNameInDev = "useCacheRefresh"; + updateHookTypesDev(); + return updateRefresh(); + }; + } + + { + HooksDispatcherOnUpdateInDEV.useMemoCache = useMemoCache; + } + + { + HooksDispatcherOnUpdateInDEV.useEffectEvent = function useEffectEvent( + callback + ) { + currentHookNameInDev = "useEffectEvent"; + updateHookTypesDev(); + return updateEvent(callback); + }; + } + + if (enableAsyncActions) { + HooksDispatcherOnUpdateInDEV.useOptimistic = function useOptimistic( + passthrough, + reducer + ) { + currentHookNameInDev = "useOptimistic"; + updateHookTypesDev(); + return updateOptimistic(passthrough, reducer); + }; + } + + HooksDispatcherOnRerenderInDEV = { + readContext: function (context) { + return readContext(context); + }, + use: use, + useCallback: function (callback, deps) { + currentHookNameInDev = "useCallback"; + updateHookTypesDev(); + return updateCallback(callback, deps); + }, + useContext: function (context) { + currentHookNameInDev = "useContext"; + updateHookTypesDev(); + return readContext(context); + }, + useEffect: function (create, deps) { + currentHookNameInDev = "useEffect"; + updateHookTypesDev(); + return updateEffect(create, deps); + }, + useImperativeHandle: function (ref, create, deps) { + currentHookNameInDev = "useImperativeHandle"; + updateHookTypesDev(); + return updateImperativeHandle(ref, create, deps); + }, + useInsertionEffect: function (create, deps) { + currentHookNameInDev = "useInsertionEffect"; + updateHookTypesDev(); + return updateInsertionEffect(create, deps); + }, + useLayoutEffect: function (create, deps) { + currentHookNameInDev = "useLayoutEffect"; + updateHookTypesDev(); + return updateLayoutEffect(create, deps); + }, + useMemo: function (create, deps) { + currentHookNameInDev = "useMemo"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnRerenderInDEV; + + try { + return updateMemo(create, deps); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useReducer: function (reducer, initialArg, init) { + currentHookNameInDev = "useReducer"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnRerenderInDEV; + + try { + return rerenderReducer(reducer, initialArg, init); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useRef: function (initialValue) { + currentHookNameInDev = "useRef"; + updateHookTypesDev(); + return updateRef(); + }, + useState: function (initialState) { + currentHookNameInDev = "useState"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnRerenderInDEV; + + try { + return rerenderState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + updateHookTypesDev(); + return updateDebugValue(); + }, + useDeferredValue: function (value, initialValue) { + currentHookNameInDev = "useDeferredValue"; + updateHookTypesDev(); + return rerenderDeferredValue(value, initialValue); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + updateHookTypesDev(); + return rerenderTransition(); + }, + useSyncExternalStore: function ( + subscribe, + getSnapshot, + getServerSnapshot + ) { + currentHookNameInDev = "useSyncExternalStore"; + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + updateHookTypesDev(); + return updateId(); + } + }; + + { + HooksDispatcherOnRerenderInDEV.useCacheRefresh = + function useCacheRefresh() { + currentHookNameInDev = "useCacheRefresh"; + updateHookTypesDev(); + return updateRefresh(); + }; + } + + { + HooksDispatcherOnRerenderInDEV.useMemoCache = useMemoCache; + } + + { + HooksDispatcherOnRerenderInDEV.useEffectEvent = function useEffectEvent( + callback + ) { + currentHookNameInDev = "useEffectEvent"; + updateHookTypesDev(); + return updateEvent(callback); + }; + } + + if (enableAsyncActions) { + HooksDispatcherOnRerenderInDEV.useOptimistic = function useOptimistic( + passthrough, + reducer + ) { + currentHookNameInDev = "useOptimistic"; + updateHookTypesDev(); + return rerenderOptimistic(passthrough, reducer); + }; + } + + InvalidNestedHooksDispatcherOnMountInDEV = { + readContext: function (context) { + warnInvalidContextAccess(); + return readContext(context); + }, + use: function (usable) { + warnInvalidHookAccess(); + return use(usable); + }, + useCallback: function (callback, deps) { + currentHookNameInDev = "useCallback"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountCallback(callback, deps); + }, + useContext: function (context) { + currentHookNameInDev = "useContext"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return readContext(context); + }, + useEffect: function (create, deps) { + currentHookNameInDev = "useEffect"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountEffect(create, deps); + }, + useImperativeHandle: function (ref, create, deps) { + currentHookNameInDev = "useImperativeHandle"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountImperativeHandle(ref, create, deps); + }, + useInsertionEffect: function (create, deps) { + currentHookNameInDev = "useInsertionEffect"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountInsertionEffect(create, deps); + }, + useLayoutEffect: function (create, deps) { + currentHookNameInDev = "useLayoutEffect"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountLayoutEffect(create, deps); + }, + useMemo: function (create, deps) { + currentHookNameInDev = "useMemo"; + warnInvalidHookAccess(); + mountHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountMemo(create, deps); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useReducer: function (reducer, initialArg, init) { + currentHookNameInDev = "useReducer"; + warnInvalidHookAccess(); + mountHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountReducer(reducer, initialArg, init); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useRef: function (initialValue) { + currentHookNameInDev = "useRef"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountRef(initialValue); + }, + useState: function (initialState) { + currentHookNameInDev = "useState"; + warnInvalidHookAccess(); + mountHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountDebugValue(); + }, + useDeferredValue: function (value, initialValue) { + currentHookNameInDev = "useDeferredValue"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountDeferredValue(value, initialValue); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountTransition(); + }, + useSyncExternalStore: function ( + subscribe, + getSnapshot, + getServerSnapshot + ) { + currentHookNameInDev = "useSyncExternalStore"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountId(); + } + }; + + { + InvalidNestedHooksDispatcherOnMountInDEV.useCacheRefresh = + function useCacheRefresh() { + currentHookNameInDev = "useCacheRefresh"; + mountHookTypesDev(); + return mountRefresh(); + }; + } + + { + InvalidNestedHooksDispatcherOnMountInDEV.useMemoCache = function ( + size + ) { + warnInvalidHookAccess(); + return useMemoCache(size); + }; + } + + { + InvalidNestedHooksDispatcherOnMountInDEV.useEffectEvent = + function useEffectEvent(callback) { + currentHookNameInDev = "useEffectEvent"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountEvent(callback); + }; + } + + if (enableAsyncActions) { + InvalidNestedHooksDispatcherOnMountInDEV.useOptimistic = + function useOptimistic(passthrough, reducer) { + currentHookNameInDev = "useOptimistic"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountOptimistic(passthrough); + }; + } + + InvalidNestedHooksDispatcherOnUpdateInDEV = { + readContext: function (context) { + warnInvalidContextAccess(); + return readContext(context); + }, + use: function (usable) { + warnInvalidHookAccess(); + return use(usable); + }, + useCallback: function (callback, deps) { + currentHookNameInDev = "useCallback"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateCallback(callback, deps); + }, + useContext: function (context) { + currentHookNameInDev = "useContext"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return readContext(context); + }, + useEffect: function (create, deps) { + currentHookNameInDev = "useEffect"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateEffect(create, deps); + }, + useImperativeHandle: function (ref, create, deps) { + currentHookNameInDev = "useImperativeHandle"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateImperativeHandle(ref, create, deps); + }, + useInsertionEffect: function (create, deps) { + currentHookNameInDev = "useInsertionEffect"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateInsertionEffect(create, deps); + }, + useLayoutEffect: function (create, deps) { + currentHookNameInDev = "useLayoutEffect"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateLayoutEffect(create, deps); + }, + useMemo: function (create, deps) { + currentHookNameInDev = "useMemo"; + warnInvalidHookAccess(); + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return updateMemo(create, deps); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useReducer: function (reducer, initialArg, init) { + currentHookNameInDev = "useReducer"; + warnInvalidHookAccess(); + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return updateReducer(reducer, initialArg, init); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useRef: function (initialValue) { + currentHookNameInDev = "useRef"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateRef(); + }, + useState: function (initialState) { + currentHookNameInDev = "useState"; + warnInvalidHookAccess(); + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return updateState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateDebugValue(); + }, + useDeferredValue: function (value, initialValue) { + currentHookNameInDev = "useDeferredValue"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateDeferredValue(value, initialValue); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateTransition(); + }, + useSyncExternalStore: function ( + subscribe, + getSnapshot, + getServerSnapshot + ) { + currentHookNameInDev = "useSyncExternalStore"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateId(); + } + }; + + { + InvalidNestedHooksDispatcherOnUpdateInDEV.useCacheRefresh = + function useCacheRefresh() { + currentHookNameInDev = "useCacheRefresh"; + updateHookTypesDev(); + return updateRefresh(); + }; + } + + { + InvalidNestedHooksDispatcherOnUpdateInDEV.useMemoCache = function ( + size + ) { + warnInvalidHookAccess(); + return useMemoCache(size); + }; + } + + { + InvalidNestedHooksDispatcherOnUpdateInDEV.useEffectEvent = + function useEffectEvent(callback) { + currentHookNameInDev = "useEffectEvent"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateEvent(callback); + }; + } + + if (enableAsyncActions) { + InvalidNestedHooksDispatcherOnUpdateInDEV.useOptimistic = + function useOptimistic(passthrough, reducer) { + currentHookNameInDev = "useOptimistic"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateOptimistic(passthrough, reducer); + }; + } + + InvalidNestedHooksDispatcherOnRerenderInDEV = { + readContext: function (context) { + warnInvalidContextAccess(); + return readContext(context); + }, + use: function (usable) { + warnInvalidHookAccess(); + return use(usable); + }, + useCallback: function (callback, deps) { + currentHookNameInDev = "useCallback"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateCallback(callback, deps); + }, + useContext: function (context) { + currentHookNameInDev = "useContext"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return readContext(context); + }, + useEffect: function (create, deps) { + currentHookNameInDev = "useEffect"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateEffect(create, deps); + }, + useImperativeHandle: function (ref, create, deps) { + currentHookNameInDev = "useImperativeHandle"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateImperativeHandle(ref, create, deps); + }, + useInsertionEffect: function (create, deps) { + currentHookNameInDev = "useInsertionEffect"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateInsertionEffect(create, deps); + }, + useLayoutEffect: function (create, deps) { + currentHookNameInDev = "useLayoutEffect"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateLayoutEffect(create, deps); + }, + useMemo: function (create, deps) { + currentHookNameInDev = "useMemo"; + warnInvalidHookAccess(); + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return updateMemo(create, deps); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useReducer: function (reducer, initialArg, init) { + currentHookNameInDev = "useReducer"; + warnInvalidHookAccess(); + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return rerenderReducer(reducer, initialArg, init); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useRef: function (initialValue) { + currentHookNameInDev = "useRef"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateRef(); + }, + useState: function (initialState) { + currentHookNameInDev = "useState"; + warnInvalidHookAccess(); + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return rerenderState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateDebugValue(); + }, + useDeferredValue: function (value, initialValue) { + currentHookNameInDev = "useDeferredValue"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return rerenderDeferredValue(value, initialValue); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return rerenderTransition(); + }, + useSyncExternalStore: function ( + subscribe, + getSnapshot, + getServerSnapshot + ) { + currentHookNameInDev = "useSyncExternalStore"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateId(); + } + }; + + { + InvalidNestedHooksDispatcherOnRerenderInDEV.useCacheRefresh = + function useCacheRefresh() { + currentHookNameInDev = "useCacheRefresh"; + updateHookTypesDev(); + return updateRefresh(); + }; + } + + { + InvalidNestedHooksDispatcherOnRerenderInDEV.useMemoCache = function ( + size + ) { + warnInvalidHookAccess(); + return useMemoCache(size); + }; + } + + { + InvalidNestedHooksDispatcherOnRerenderInDEV.useEffectEvent = + function useEffectEvent(callback) { + currentHookNameInDev = "useEffectEvent"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateEvent(callback); + }; + } + + if (enableAsyncActions) { + InvalidNestedHooksDispatcherOnRerenderInDEV.useOptimistic = + function useOptimistic(passthrough, reducer) { + currentHookNameInDev = "useOptimistic"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return rerenderOptimistic(passthrough, reducer); + }; } } - }); - return resultThenable; -} -function requestSyncActionContext( - actionReturnValue, // If this is provided, this resulting thenable resolves to this value instead - // of the return value of the action. This is a perf trick to avoid composing - // an extra async function. - overrideReturnValue -) { - var resultValue = - overrideReturnValue !== null ? overrideReturnValue : actionReturnValue; // This is not an async action, but it may be part of an outer async action. - - if (currentEntangledListeners === null) { - return resultValue; - } else { - // Return a thenable that does not resolve until the entangled actions - // have finished. - var entangledListeners = currentEntangledListeners; - var resultThenable = createResultThenable(entangledListeners); - entangledListeners.push(function () { - var fulfilledThenable = resultThenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = resultValue; - }); - return resultThenable; - } -} - -function pingEngtangledActionScope() { - if ( - currentEntangledListeners !== null && - --currentEntangledPendingCount === 0 - ) { - // All the actions have finished. Close the entangled async action scope - // and notify all the listeners. - var listeners = currentEntangledListeners; - currentEntangledListeners = null; - currentEntangledLane = NoLane; - - for (var i = 0; i < listeners.length; i++) { - var listener = listeners[i]; - listener(); - } - } -} -function createResultThenable(entangledListeners) { - // Waits for the entangled async action to complete, then resolves to the - // result of an individual action. - var resultThenable = { - status: "pending", - value: null, - reason: null, - then: function (resolve) { - // This is a bit of a cheat. `resolve` expects a value of type `S` to be - // passed, but because we're instrumenting the `status` field ourselves, - // and we know this thenable will only be used by React, we also know - // the value isn't actually needed. So we add the resolve function - // directly to the entangled listeners. - // - // This is also why we don't need to check if the thenable is still - // pending; the Suspense implementation already performs that check. - var ping = resolve; - entangledListeners.push(ping); + var now = Scheduler.unstable_now; + var commitTime = 0; + var layoutEffectStartTime = -1; + var profilerStartTime = -1; + var passiveEffectStartTime = -1; + /** + * Tracks whether the current update was a nested/cascading update (scheduled from a layout effect). + * + * The overall sequence is: + * 1. render + * 2. commit (and call `onRender`, `onCommit`) + * 3. check for nested updates + * 4. flush passive effects (and call `onPostCommit`) + * + * Nested updates are identified in step 3 above, + * but step 4 still applies to the work that was just committed. + * We use two flags to track nested updates then: + * one tracks whether the upcoming update is a nested update, + * and the other tracks whether the current update was a nested update. + * The first value gets synced to the second at the start of the render phase. + */ + + var currentUpdateIsNested = false; + var nestedUpdateScheduled = false; + + function isCurrentUpdateNested() { + return currentUpdateIsNested; + } + + function markNestedUpdateScheduled() { + { + nestedUpdateScheduled = true; + } } - }; - return resultThenable; -} - -function peekEntangledActionLane() { - return currentEntangledLane; -} -var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, - ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig; -var didWarnAboutMismatchedHooksForComponent; -var didWarnUncachedGetSnapshot; -var didWarnAboutUseWrappedInTryCatch; -var didWarnAboutAsyncClientComponent; - -{ - didWarnAboutMismatchedHooksForComponent = new Set(); - didWarnAboutUseWrappedInTryCatch = new Set(); - didWarnAboutAsyncClientComponent = new Set(); -} // The effect "instance" is a shared object that remains the same for the entire -// lifetime of an effect. In Rust terms, a RefCell. We use it to store the -// "destroy" function that is returned from an effect, because that is stateful. -// The field is `undefined` if the effect is unmounted, or if the effect ran -// but is not stateful. We don't explicitly track whether the effect is mounted -// or unmounted because that can be inferred by the hiddenness of the fiber in -// the tree, i.e. whether there is a hidden Offscreen fiber above it. -// -// It's unfortunate that this is stored on a separate object, because it adds -// more memory per effect instance, but it's conceptually sound. I think there's -// likely a better data structure we could use for effects; perhaps just one -// array of effect instances per fiber. But I think this is OK for now despite -// the additional memory and we can follow up with performance -// optimizations later. -// These are set right before calling the component. - -var renderLanes = NoLanes; // The work-in-progress fiber. I've named it differently to distinguish it from -// the work-in-progress hook. - -var currentlyRenderingFiber$1 = null; // Hooks are stored as a linked list on the fiber's memoizedState field. The -// current hook list is the list that belongs to the current fiber. The -// work-in-progress hook list is a new list that will be added to the -// work-in-progress fiber. - -var currentHook = null; -var workInProgressHook = null; // Whether an update was scheduled at any point during the render phase. This -// does not get reset if we do another render pass; only when we're completely -// finished evaluating this component. This is an optimization so we know -// whether we need to clear render phase updates after a throw. - -var didScheduleRenderPhaseUpdate = false; // Where an update was scheduled only during the current render pass. This -// gets reset after each attempt. -// TODO: Maybe there's some way to consolidate this with -// `didScheduleRenderPhaseUpdate`. Or with `numberOfReRenders`. - -var didScheduleRenderPhaseUpdateDuringThisPass = false; -var shouldDoubleInvokeUserFnsInHooksDEV = false; // Counts the number of useId hooks in this component. - -var thenableIndexCounter = 0; -var thenableState = null; // Used for ids that are generated completely client-side (i.e. not during -// hydration). This counter is global, so client ids are not stable across -// render attempts. - -var globalClientIdCounter = 0; -var RE_RENDER_LIMIT = 25; // In DEV, this is the name of the currently executing primitive hook - -var currentHookNameInDev = null; // In DEV, this list ensures that hooks are called in the same order between renders. -// The list stores the order of hooks used during the initial render (mount). -// Subsequent renders (updates) reference this list. - -var hookTypesDev = null; -var hookTypesUpdateIndexDev = -1; // In DEV, this tracks whether currently rendering component needs to ignore -// the dependencies for Hooks that need them (e.g. useEffect or useMemo). -// When true, such Hooks will always be "remounted". Only used during hot reload. - -var ignorePreviousDependencies = false; - -function mountHookTypesDev() { - { - var hookName = currentHookNameInDev; - - if (hookTypesDev === null) { - hookTypesDev = [hookName]; - } else { - hookTypesDev.push(hookName); + function resetNestedUpdateFlag() { + { + currentUpdateIsNested = false; + nestedUpdateScheduled = false; + } } - } -} - -function updateHookTypesDev() { - { - var hookName = currentHookNameInDev; - if (hookTypesDev !== null) { - hookTypesUpdateIndexDev++; - - if (hookTypesDev[hookTypesUpdateIndexDev] !== hookName) { - warnOnHookMismatchInDev(hookName); + function syncNestedUpdateFlag() { + { + currentUpdateIsNested = nestedUpdateScheduled; + nestedUpdateScheduled = false; } } - } -} -function checkDepsAreArrayDev(deps) { - { - if (deps !== undefined && deps !== null && !isArray(deps)) { - // Verify deps, but only on mount to avoid extra checks. - // It's unlikely their type would change as usually you define them inline. - 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 - ); + function getCommitTime() { + return commitTime; } - } -} -function warnOnHookMismatchInDev(currentHookName) { - { - var componentName = getComponentNameFromFiber(currentlyRenderingFiber$1); + function recordCommitTime() { + commitTime = now(); + } - if (!didWarnAboutMismatchedHooksForComponent.has(componentName)) { - didWarnAboutMismatchedHooksForComponent.add(componentName); + function startProfilerTimer(fiber) { + profilerStartTime = now(); - if (hookTypesDev !== null) { - var table = ""; - var secondColumnStart = 30; + if (fiber.actualStartTime < 0) { + fiber.actualStartTime = now(); + } + } - for (var i = 0; i <= hookTypesUpdateIndexDev; i++) { - var oldHookName = hookTypesDev[i]; - var newHookName = - i === hookTypesUpdateIndexDev ? currentHookName : oldHookName; - var row = i + 1 + ". " + oldHookName; // Extra space so second column lines up - // lol @ IE not supporting String#repeat + function stopProfilerTimerIfRunning(fiber) { + profilerStartTime = -1; + } - while (row.length < secondColumnStart) { - row += " "; - } + function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { + if (profilerStartTime >= 0) { + var elapsedTime = now() - profilerStartTime; + fiber.actualDuration += elapsedTime; - row += newHookName + "\n"; - table += row; + if (overrideBaseTime) { + fiber.selfBaseDuration = elapsedTime; } - 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 - ); + profilerStartTime = -1; } } - } -} -function warnIfAsyncClientComponent(Component, componentDoesIncludeHooks) { - { - // This dev-only check only works for detecting native async functions, - // not transpiled ones. There's also a prod check that we use to prevent - // async client components from crashing the app; the prod one works even - // for transpiled async functions. Neither mechanism is completely - // bulletproof but together they cover the most common cases. - var isAsyncFunction = // $FlowIgnore[method-unbinding] - Object.prototype.toString.call(Component) === "[object AsyncFunction]"; - - if (isAsyncFunction) { - // Encountered an async Client Component. This is not yet supported, - // except in certain constrained cases, like during a route navigation. - var componentName = getComponentNameFromFiber(currentlyRenderingFiber$1); - - if (!didWarnAboutAsyncClientComponent.has(componentName)) { - didWarnAboutAsyncClientComponent.add(componentName); // Check if this is a sync update. We use the "root" render lanes here - // because the "subtree" render lanes may include additional entangled - // lanes related to revealing previously hidden content. + function recordLayoutEffectDuration(fiber) { + if (layoutEffectStartTime >= 0) { + var elapsedTime = now() - layoutEffectStartTime; + layoutEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor + // Or the root (for the DevTools Profiler to read) - var root = getWorkInProgressRoot(); - var rootRenderLanes = getWorkInProgressRootRenderLanes(); + var parentFiber = fiber.return; - if (root !== null && includesBlockingLane(root, rootRenderLanes)) { - error( - "async/await is not yet supported in Client Components, only " + - "Server Components. This error is often caused by accidentally " + - "adding `'use client'` to a module that was originally written " + - "for the server." - ); - } else { - // This is a concurrent (Transition, Retry, etc) render. We don't - // warn in these cases. - // - // However, Async Components are forbidden to include hooks, even - // during a transition, so let's check for that here. - // - // TODO: Add a corresponding warning to Server Components runtime. - if (componentDoesIncludeHooks) { - error( - "Hooks are not supported inside an async component. This " + - "error is often caused by accidentally adding `'use client'` " + - "to a module that was originally written for the server." - ); + while (parentFiber !== null) { + switch (parentFiber.tag) { + case HostRoot: + var root = parentFiber.stateNode; + root.effectDuration += elapsedTime; + return; + + case Profiler: + var parentStateNode = parentFiber.stateNode; + parentStateNode.effectDuration += elapsedTime; + return; } + + parentFiber = parentFiber.return; } } } - } -} - -function throwInvalidHookError() { - 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." - ); -} -function areHookInputsEqual(nextDeps, prevDeps) { - { - if (ignorePreviousDependencies) { - // Only true when this component is being hot reloaded. - return false; - } - } + function recordPassiveEffectDuration(fiber) { + if (passiveEffectStartTime >= 0) { + var elapsedTime = now() - passiveEffectStartTime; + passiveEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor + // Or the root (for the DevTools Profiler to read) - if (prevDeps === null) { - { - 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 - ); - } + var parentFiber = fiber.return; - return false; - } - - { - // Don't bother comparing lengths in prod because these arrays should be - // passed inline. - if (nextDeps.length !== prevDeps.length) { - 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(", ") + "]" - ); - } - } // $FlowFixMe[incompatible-use] found when upgrading Flow + while (parentFiber !== null) { + switch (parentFiber.tag) { + case HostRoot: + var root = parentFiber.stateNode; - for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - if (objectIs(nextDeps[i], prevDeps[i])) { - continue; - } + if (root !== null) { + root.passiveEffectDuration += elapsedTime; + } - return false; - } + return; - return true; -} + case Profiler: + var parentStateNode = parentFiber.stateNode; -function renderWithHooks( - current, - workInProgress, - Component, - props, - secondArg, - nextRenderLanes -) { - renderLanes = nextRenderLanes; - currentlyRenderingFiber$1 = workInProgress; - - { - hookTypesDev = current !== null ? current._debugHookTypes : null; - hookTypesUpdateIndexDev = -1; // Used for hot reloading: - - ignorePreviousDependencies = - current !== null && current.type !== workInProgress.type; - } - - workInProgress.memoizedState = null; - workInProgress.updateQueue = null; - workInProgress.lanes = NoLanes; // The following should have already been reset - // currentHook = null; - // workInProgressHook = null; - // didScheduleRenderPhaseUpdate = false; - // localIdCounter = 0; - // thenableIndexCounter = 0; - // thenableState = null; - // TODO Warn if no hooks are used at all during mount, then some are used during update. - // Currently we will identify the update render as a mount because memoizedState === null. - // This is tricky because it's valid for certain types of components (e.g. React.lazy) - // Using memoizedState to differentiate between mount/update only works if at least one stateful hook is used. - // Non-stateful hooks (e.g. context) don't get added to memoizedState, - // so memoizedState would be null during updates and mounts. - - { - if (current !== null && current.memoizedState !== null) { - ReactCurrentDispatcher$1.current = HooksDispatcherOnUpdateInDEV; - } else if (hookTypesDev !== null) { - // This dispatcher handles an edge case where a component is updating, - // but no stateful hooks have been used. - // We want to match the production code behavior (which will use HooksDispatcherOnMount), - // but with the extra DEV validation to ensure hooks ordering hasn't changed. - // This dispatcher does that. - ReactCurrentDispatcher$1.current = - HooksDispatcherOnMountWithHookTypesInDEV; - } else { - ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; - } - } // In Strict Mode, during development, user functions are double invoked to - // help detect side effects. The logic for how this is implemented for in - // hook components is a bit complex so let's break it down. - // - // We will invoke the entire component function twice. However, during the - // second invocation of the component, the hook state from the first - // invocation will be reused. That means things like `useMemo` functions won't - // run again, because the deps will match and the memoized result will - // be reused. - // - // We want memoized functions to run twice, too, so account for this, user - // functions are double invoked during the *first* invocation of the component - // function, and are *not* double invoked during the second incovation: - // - // - First execution of component function: user functions are double invoked - // - Second execution of component function (in Strict Mode, during - // development): user functions are not double invoked. - // - // This is intentional for a few reasons; most importantly, it's because of - // how `use` works when something suspends: it reuses the promise that was - // passed during the first attempt. This is itself a form of memoization. - // We need to be able to memoize the reactive inputs to the `use` call using - // a hook (i.e. `useMemo`), which means, the reactive inputs to `use` must - // come from the same component invocation as the output. - // - // There are plenty of tests to ensure this behavior is correct. - - var shouldDoubleRenderDEV = - (workInProgress.mode & StrictLegacyMode) !== NoMode; - shouldDoubleInvokeUserFnsInHooksDEV = shouldDoubleRenderDEV; - var children = Component(props, secondArg); - shouldDoubleInvokeUserFnsInHooksDEV = false; // Check if there was a render phase update - - if (didScheduleRenderPhaseUpdateDuringThisPass) { - // Keep rendering until the component stabilizes (there are no more render - // phase updates). - children = renderWithHooksAgain( - workInProgress, - Component, - props, - secondArg - ); - } + if (parentStateNode !== null) { + // Detached fibers have their state node cleared out. + // In this case, the return pointer is also cleared out, + // so we won't be able to report the time spent in this Profiler's subtree. + parentStateNode.passiveEffectDuration += elapsedTime; + } - if (shouldDoubleRenderDEV) { - // In development, components are invoked twice to help detect side effects. - setIsStrictModeForDevtools(true); + return; + } - try { - children = renderWithHooksAgain( - workInProgress, - Component, - props, - secondArg - ); - } finally { - setIsStrictModeForDevtools(false); + parentFiber = parentFiber.return; + } + } } - } - finishRenderingHooks(current, workInProgress, Component); - return children; -} - -function finishRenderingHooks(current, workInProgress, Component) { - { - workInProgress._debugHookTypes = hookTypesDev; - var componentDoesIncludeHooks = - workInProgressHook !== null || thenableIndexCounter !== 0; - warnIfAsyncClientComponent(Component, componentDoesIncludeHooks); - } // We can assume the previous dispatcher is always this one, since we set it - // at the beginning of the render phase and there's no re-entrance. - - ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; // This check uses currentHook so that it works the same in DEV and prod bundles. - // hookTypesDev could catch more cases (e.g. context) but only in DEV bundles. - - var didRenderTooFewHooks = currentHook !== null && currentHook.next !== null; - renderLanes = NoLanes; - currentlyRenderingFiber$1 = null; - currentHook = null; - workInProgressHook = null; - - { - currentHookNameInDev = null; - hookTypesDev = null; - hookTypesUpdateIndexDev = -1; // Confirm that a static flag was not added or removed since the last - // render. If this fires, it suggests that we incorrectly reset the static - // flags in some other part of the codebase. This has happened before, for - // example, in the SuspenseList implementation. - - if ( - current !== null && - (current.flags & StaticMask) !== (workInProgress.flags & StaticMask) && // Disable this warning in legacy mode, because legacy Suspense is weird - // and creates false positives. To make this work in legacy mode, we'd - // need to mark fibers that commit in an incomplete state, somehow. For - // now I'll disable the warning that most of the bugs that would trigger - // it are either exclusive to concurrent mode or exist in both. - (current.mode & ConcurrentMode) !== NoMode - ) { - error( - "Internal React error: Expected static flag was missing. Please " + - "notify the React team." - ); + function startLayoutEffectTimer() { + layoutEffectStartTime = now(); } - } - - didScheduleRenderPhaseUpdate = false; // This is reset by checkDidRenderIdHook - // localIdCounter = 0; - - thenableIndexCounter = 0; - thenableState = null; - if (didRenderTooFewHooks) { - throw new Error( - "Rendered fewer hooks than expected. This may be caused by an accidental " + - "early return statement." - ); - } - - if (enableLazyContextPropagation) { - if (current !== null) { - if (!checkIfWorkInProgressReceivedUpdate()) { - // If there were no changes to props or state, we need to check if there - // was a context change. We didn't already do this because there's no - // 1:1 correspondence between dependencies and hooks. Although, because - // there almost always is in the common case (`readContext` is an - // internal API), we could compare in there. OTOH, we only hit this case - // if everything else bails out, so on the whole it might be better to - // keep the comparison out of the common path. - var currentDependencies = current.dependencies; - - if ( - currentDependencies !== null && - checkIfContextChanged(currentDependencies) - ) { - markWorkInProgressReceivedUpdate(); - } - } + function startPassiveEffectTimer() { + passiveEffectStartTime = now(); } - } - { - if (checkIfUseWrappedInTryCatch()) { - var componentName = - getComponentNameFromFiber(workInProgress) || "Unknown"; + function transferActualDuration(fiber) { + // Transfer time spent rendering these children so we don't lose it + // after we rerender. This is used as a helper in special cases + // where we should count the work of multiple passes. + var child = fiber.child; - if ( - !didWarnAboutUseWrappedInTryCatch.has(componentName) && // This warning also fires if you suspend with `use` inside an - // async component. Since we warn for that above, we'll silence this - // second warning by checking here. - !didWarnAboutAsyncClientComponent.has(componentName) - ) { - didWarnAboutUseWrappedInTryCatch.add(componentName); - - error( - "`use` was called from inside a try/catch block. This is not allowed " + - "and can lead to unexpected behavior. To handle errors triggered " + - "by `use`, wrap your component in a error boundary." - ); + while (child) { + // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + fiber.actualDuration += child.actualDuration; + child = child.sibling; } } - } -} -function replaySuspendedComponentWithHooks( - current, - workInProgress, - Component, - props, - secondArg -) { - // This function is used to replay a component that previously suspended, - // after its data resolves. - // - // It's a simplified version of renderWithHooks, but it doesn't need to do - // most of the set up work because they weren't reset when we suspended; they - // only get reset when the component either completes (finishRenderingHooks) - // or unwinds (resetHooksOnUnwind). - { - hookTypesUpdateIndexDev = -1; // Used for hot reloading: - - ignorePreviousDependencies = - current !== null && current.type !== workInProgress.type; - } - - var children = renderWithHooksAgain( - workInProgress, - Component, - props, - secondArg - ); - finishRenderingHooks(current, workInProgress, Component); - return children; -} + function resolveDefaultProps(Component, baseProps) { + if (Component && Component.defaultProps) { + // Resolve default props. Taken from ReactElement + var props = assign({}, baseProps); + var defaultProps = Component.defaultProps; -function renderWithHooksAgain(workInProgress, Component, props, secondArg) { - // This is used to perform another render pass. It's used when setState is - // called during render, and for double invoking components in Strict Mode - // during development. - // - // The state from the previous pass is reused whenever possible. So, state - // updates that were already processed are not processed again, and memoized - // functions (`useMemo`) are not invoked again. - // - // Keep rendering in a loop for as long as render phase updates continue to - // be scheduled. Use a counter to prevent infinite loops. - currentlyRenderingFiber$1 = workInProgress; - var numberOfReRenders = 0; - var children; - - do { - if (didScheduleRenderPhaseUpdateDuringThisPass) { - // It's possible that a use() value depended on a state that was updated in - // this rerender, so we need to watch for different thenables this time. - thenableState = null; - } + for (var propName in defaultProps) { + if (props[propName] === undefined) { + props[propName] = defaultProps[propName]; + } + } - thenableIndexCounter = 0; - didScheduleRenderPhaseUpdateDuringThisPass = false; + return props; + } - if (numberOfReRenders >= RE_RENDER_LIMIT) { - throw new Error( - "Too many re-renders. React limits the number of renders to prevent " + - "an infinite loop." - ); + return baseProps; } - numberOfReRenders += 1; - - { - // Even when hot reloading, allow dependencies to stabilize - // after first render to prevent infinite render phase updates. - ignorePreviousDependencies = false; - } // Start over from the beginning of the list - - currentHook = null; - workInProgressHook = null; - workInProgress.updateQueue = null; + var fakeInternalInstance = {}; + var didWarnAboutStateAssignmentForComponent; + var didWarnAboutUninitializedState; + var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate; + var didWarnAboutLegacyLifecyclesAndDerivedState; + var didWarnAboutUndefinedDerivedState; + var didWarnAboutDirectlyAssigningPropsToState; + var didWarnAboutContextTypeAndContextTypes; + var didWarnAboutInvalidateContextType; + var didWarnOnInvalidCallback; { - // Also validate hook order for cascading updates. - hookTypesUpdateIndexDev = -1; + didWarnAboutStateAssignmentForComponent = new Set(); + didWarnAboutUninitializedState = new Set(); + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set(); + didWarnAboutLegacyLifecyclesAndDerivedState = new Set(); + didWarnAboutDirectlyAssigningPropsToState = new Set(); + didWarnAboutUndefinedDerivedState = new Set(); + didWarnAboutContextTypeAndContextTypes = new Set(); + didWarnAboutInvalidateContextType = new Set(); + didWarnOnInvalidCallback = new Set(); // This is so gross but it's at least non-critical and can be removed if + // it causes problems. This is meant to give a nicer error message for + // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component, + // ...)) which otherwise throws a "_processChildContext is not a function" + // exception. + + Object.defineProperty(fakeInternalInstance, "_processChildContext", { + enumerable: false, + value: function () { + 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)." + ); + } + }); + Object.freeze(fakeInternalInstance); } - ReactCurrentDispatcher$1.current = HooksDispatcherOnRerenderInDEV; - children = Component(props, secondArg); - } while (didScheduleRenderPhaseUpdateDuringThisPass); - - return children; -} -function bailoutHooks(current, workInProgress, lanes) { - workInProgress.updateQueue = current.updateQueue; // TODO: Don't need to reset the flags here, because they're reset in the - // complete phase (bubbleProperties). - - if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { - workInProgress.flags &= ~( - MountPassiveDev | - MountLayoutDev | - Passive$1 | - Update - ); - } else { - workInProgress.flags &= ~(Passive$1 | Update); - } + function warnOnInvalidCallback(callback, callerName) { + { + if (callback === null || typeof callback === "function") { + return; + } - current.lanes = removeLanes(current.lanes, lanes); -} -function resetHooksAfterThrow() { - // This is called immediaetly after a throw. It shouldn't reset the entire - // module state, because the work loop might decide to replay the component - // again without rewinding. - // - // It should only reset things like the current dispatcher, to prevent hooks - // from being called outside of a component. - currentlyRenderingFiber$1 = null; // We can assume the previous dispatcher is always this one, since we set it - // at the beginning of the render phase and there's no re-entrance. - - ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; -} -function resetHooksOnUnwind(workInProgress) { - if (didScheduleRenderPhaseUpdate) { - // There were render phase updates. These are only valid for this render - // phase, which we are now aborting. Remove the updates from the queues so - // they do not persist to the next render. Do not remove updates from hooks - // that weren't processed. - // - // Only reset the updates from the queue if it has a clone. If it does - // not have a clone, that means it wasn't processed, and the updates were - // scheduled before we entered the render phase. - var hook = workInProgress.memoizedState; + var key = callerName + "_" + callback; - while (hook !== null) { - var queue = hook.queue; + if (!didWarnOnInvalidCallback.has(key)) { + didWarnOnInvalidCallback.add(key); - if (queue !== null) { - queue.pending = null; + error( + "%s(...): Expected the last optional `callback` argument to be a " + + "function. Instead received: %s.", + callerName, + callback + ); + } } - - hook = hook.next; } - didScheduleRenderPhaseUpdate = false; - } - - renderLanes = NoLanes; - currentlyRenderingFiber$1 = null; - currentHook = null; - workInProgressHook = null; - - { - hookTypesDev = null; - hookTypesUpdateIndexDev = -1; - currentHookNameInDev = null; - } - - didScheduleRenderPhaseUpdateDuringThisPass = false; - thenableIndexCounter = 0; - thenableState = null; -} - -function mountWorkInProgressHook() { - var hook = { - memoizedState: null, - baseState: null, - baseQueue: null, - queue: null, - next: null - }; - - if (workInProgressHook === null) { - // This is the first hook in the list - currentlyRenderingFiber$1.memoizedState = workInProgressHook = hook; - } else { - // Append to the end of the list - workInProgressHook = workInProgressHook.next = hook; - } - - return workInProgressHook; -} - -function updateWorkInProgressHook() { - // This function is used both for updates and for re-renders triggered by a - // render phase update. It assumes there is either a current hook we can - // clone, or a work-in-progress hook from a previous render pass that we can - // use as a base. - var nextCurrentHook; - - if (currentHook === null) { - var current = currentlyRenderingFiber$1.alternate; + function warnOnUndefinedDerivedState(type, partialState) { + { + if (partialState === undefined) { + var componentName = getComponentNameFromType(type) || "Component"; - if (current !== null) { - nextCurrentHook = current.memoizedState; - } else { - nextCurrentHook = null; - } - } else { - nextCurrentHook = currentHook.next; - } - - var nextWorkInProgressHook; - - if (workInProgressHook === null) { - nextWorkInProgressHook = currentlyRenderingFiber$1.memoizedState; - } else { - nextWorkInProgressHook = workInProgressHook.next; - } - - if (nextWorkInProgressHook !== null) { - // There's already a work-in-progress. Reuse it. - workInProgressHook = nextWorkInProgressHook; - nextWorkInProgressHook = workInProgressHook.next; - currentHook = nextCurrentHook; - } else { - // Clone from the current hook. - if (nextCurrentHook === null) { - var currentFiber = currentlyRenderingFiber$1.alternate; + if (!didWarnAboutUndefinedDerivedState.has(componentName)) { + didWarnAboutUndefinedDerivedState.add(componentName); - if (currentFiber === null) { - // This is the initial render. This branch is reached when the component - // suspends, resumes, then renders an additional hook. - // Should never be reached because we should switch to the mount dispatcher first. - throw new Error( - "Update hook called on initial render. This is likely a bug in React. Please file an issue." - ); - } else { - // This is an update. We should always have a current hook. - throw new Error("Rendered more hooks than during the previous render."); + error( + "%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. " + + "You have returned undefined.", + componentName + ); + } + } } } - currentHook = nextCurrentHook; - var newHook = { - memoizedState: currentHook.memoizedState, - baseState: currentHook.baseState, - baseQueue: currentHook.baseQueue, - queue: currentHook.queue, - next: null - }; - - if (workInProgressHook === null) { - // This is the first hook in the list. - currentlyRenderingFiber$1.memoizedState = workInProgressHook = newHook; - } else { - // Append to the end of the list. - workInProgressHook = workInProgressHook.next = newHook; - } - } - - return workInProgressHook; -} // NOTE: defining two versions of this function to avoid size impact when this feature is disabled. -// Previously this function was inlined, the additional `memoCache` property makes it not inlined. + function applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + nextProps + ) { + var prevState = workInProgress.memoizedState; + var partialState = getDerivedStateFromProps(nextProps, prevState); -var createFunctionComponentUpdateQueue; + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); -{ - createFunctionComponentUpdateQueue = function () { - return { - lastEffect: null, - events: null, - stores: null, - memoCache: null - }; - }; -} + try { + // Invoke the function an extra time to help detect side-effects. + partialState = getDerivedStateFromProps(nextProps, prevState); + } finally { + setIsStrictModeForDevtools(false); + } + } -function useThenable(thenable) { - // Track the position of the thenable within this fiber. - var index = thenableIndexCounter; - thenableIndexCounter += 1; - - if (thenableState === null) { - thenableState = createThenableState(); - } - - var result = trackUsedThenable(thenableState, thenable, index); - - if ( - currentlyRenderingFiber$1.alternate === null && - (workInProgressHook === null - ? currentlyRenderingFiber$1.memoizedState === null - : workInProgressHook.next === null) - ) { - // Initial render, and either this is the first time the component is - // called, or there were no Hooks called after this use() the previous - // time (perhaps because it threw). Subsequent Hook calls should use the - // mount dispatcher. - { - ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; - } - } + warnOnUndefinedDerivedState(ctor, partialState); + } // Merge the partial state and the previous state. - return result; -} + var memoizedState = + partialState === null || partialState === undefined + ? prevState + : assign({}, prevState, partialState); + workInProgress.memoizedState = memoizedState; // Once the update queue is empty, persist the derived state onto the + // base state. -function use(usable) { - if (usable !== null && typeof usable === "object") { - // $FlowFixMe[method-unbinding] - if (typeof usable.then === "function") { - // This is a thenable. - var thenable = usable; - return useThenable(thenable); - } else if ( - usable.$$typeof === REACT_CONTEXT_TYPE || - usable.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = usable; - return readContext(context); + if (workInProgress.lanes === NoLanes) { + // Queue is always non-null for classes + var updateQueue = workInProgress.updateQueue; + updateQueue.baseState = memoizedState; + } } - } // eslint-disable-next-line react-internal/safe-string-coercion - throw new Error("An unsupported type was passed to use(): " + String(usable)); -} + var classComponentUpdater = { + isMounted: isMounted, + // $FlowFixMe[missing-local-annot] + enqueueSetState: function (inst, payload, callback) { + var fiber = get(inst); + var lane = requestUpdateLane(fiber); + var update = createUpdate(lane); + update.payload = payload; -function useMemoCache(size) { - var memoCache = null; // Fast-path, load memo cache from wip fiber if already prepared + if (callback !== undefined && callback !== null) { + { + warnOnInvalidCallback(callback, "setState"); + } - var updateQueue = currentlyRenderingFiber$1.updateQueue; + update.callback = callback; + } - if (updateQueue !== null) { - memoCache = updateQueue.memoCache; - } // Otherwise clone from the current fiber + var root = enqueueUpdate(fiber, update, lane); - if (memoCache == null) { - var current = currentlyRenderingFiber$1.alternate; + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane); + entangleTransitions(root, fiber, lane); + } - if (current !== null) { - var currentUpdateQueue = current.updateQueue; + { + if (enableDebugTracing) { + if (fiber.mode & DebugTracingMode) { + var name = getComponentNameFromFiber(fiber) || "Unknown"; + logStateUpdateScheduled(name, lane, payload); + } + } + } - if (currentUpdateQueue !== null) { - var currentMemoCache = currentUpdateQueue.memoCache; + if (enableSchedulingProfiler) { + markStateUpdateScheduled(fiber, lane); + } + }, + enqueueReplaceState: function (inst, payload, callback) { + var fiber = get(inst); + var lane = requestUpdateLane(fiber); + var update = createUpdate(lane); + update.tag = ReplaceState; + update.payload = payload; + + if (callback !== undefined && callback !== null) { + { + warnOnInvalidCallback(callback, "replaceState"); + } - if (currentMemoCache != null) { - memoCache = { - data: currentMemoCache.data.map(function (array) { - return array.slice(); - }), - index: 0 - }; + update.callback = callback; } - } - } - } // Finally fall back to allocating a fresh instance of the cache - if (memoCache == null) { - memoCache = { - data: [], - index: 0 - }; - } + var root = enqueueUpdate(fiber, update, lane); - if (updateQueue === null) { - updateQueue = createFunctionComponentUpdateQueue(); - currentlyRenderingFiber$1.updateQueue = updateQueue; - } + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane); + entangleTransitions(root, fiber, lane); + } - updateQueue.memoCache = memoCache; - var data = memoCache.data[memoCache.index]; + { + if (enableDebugTracing) { + if (fiber.mode & DebugTracingMode) { + var name = getComponentNameFromFiber(fiber) || "Unknown"; + logStateUpdateScheduled(name, lane, payload); + } + } + } - if (data === undefined) { - data = memoCache.data[memoCache.index] = new Array(size); + if (enableSchedulingProfiler) { + markStateUpdateScheduled(fiber, lane); + } + }, + // $FlowFixMe[missing-local-annot] + enqueueForceUpdate: function (inst, callback) { + var fiber = get(inst); + var lane = requestUpdateLane(fiber); + var update = createUpdate(lane); + update.tag = ForceUpdate; + + if (callback !== undefined && callback !== null) { + { + warnOnInvalidCallback(callback, "forceUpdate"); + } - for (var i = 0; i < size; i++) { - data[i] = REACT_MEMO_CACHE_SENTINEL; - } - } else if (data.length !== size) { - // TODO: consider warning or throwing here - { - error( - "Expected a constant size argument for each invocation of useMemoCache. " + - "The previous cache was allocated with size %s but size %s was requested.", - data.length, - size - ); - } - } + update.callback = callback; + } - memoCache.index++; - return data; -} + var root = enqueueUpdate(fiber, update, lane); -function basicStateReducer(state, action) { - // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types - return typeof action === "function" ? action(state) : action; -} + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane); + entangleTransitions(root, fiber, lane); + } -function mountReducer(reducer, initialArg, init) { - var hook = mountWorkInProgressHook(); - var initialState; - - if (init !== undefined) { - initialState = init(initialArg); - } else { - initialState = initialArg; - } - - hook.memoizedState = hook.baseState = initialState; - var queue = { - pending: null, - lanes: NoLanes, - dispatch: null, - lastRenderedReducer: reducer, - lastRenderedState: initialState - }; - hook.queue = queue; - var dispatch = (queue.dispatch = dispatchReducerAction.bind( - null, - currentlyRenderingFiber$1, - queue - )); - return [hook.memoizedState, dispatch]; -} + { + if (enableDebugTracing) { + if (fiber.mode & DebugTracingMode) { + var name = getComponentNameFromFiber(fiber) || "Unknown"; + logForceUpdateScheduled(name, lane); + } + } + } -function updateReducer(reducer, initialArg, init) { - var hook = updateWorkInProgressHook(); - return updateReducerImpl(hook, currentHook, reducer); -} + if (enableSchedulingProfiler) { + markForceUpdateScheduled(fiber, lane); + } + } + }; -function updateReducerImpl(hook, current, reducer) { - var queue = hook.queue; + function checkShouldComponentUpdate( + workInProgress, + ctor, + oldProps, + newProps, + oldState, + newState, + nextContext + ) { + var instance = workInProgress.stateNode; - if (queue === null) { - throw new Error( - "Should have a queue. This is likely a bug in React. Please file an issue." - ); - } + if (typeof instance.shouldComponentUpdate === "function") { + var shouldUpdate = instance.shouldComponentUpdate( + newProps, + newState, + nextContext + ); - queue.lastRenderedReducer = reducer; // The last rebase update that is NOT part of the base state. + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); - var baseQueue = hook.baseQueue; // The last pending update that hasn't been processed yet. + try { + // Invoke the function an extra time to help detect side-effects. + shouldUpdate = instance.shouldComponentUpdate( + newProps, + newState, + nextContext + ); + } finally { + setIsStrictModeForDevtools(false); + } + } - var pendingQueue = queue.pending; + if (shouldUpdate === undefined) { + error( + "%s.shouldComponentUpdate(): Returned undefined instead of a " + + "boolean value. Make sure to return true or false.", + getComponentNameFromType(ctor) || "Component" + ); + } + } - if (pendingQueue !== null) { - // We have new updates that haven't been processed yet. - // We'll add them to the base queue. - if (baseQueue !== null) { - // Merge the pending queue and the base queue. - var baseFirst = baseQueue.next; - var pendingFirst = pendingQueue.next; - baseQueue.next = pendingFirst; - pendingQueue.next = baseFirst; - } + return shouldUpdate; + } - { - if (current.baseQueue !== baseQueue) { - // Internal invariant that should never happen, but feasibly could in - // the future if we implement resuming, or some form of that. - error( - "Internal error: Expected work-in-progress queue to be a clone. " + - "This is a bug in React." + if (ctor.prototype && ctor.prototype.isPureReactComponent) { + return ( + !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) ); } + + return true; } - current.baseQueue = baseQueue = pendingQueue; - queue.pending = null; - } - - if (baseQueue !== null) { - // We have a queue to process. - var first = baseQueue.next; - var newState = hook.baseState; - var newBaseState = null; - var newBaseQueueFirst = null; - var newBaseQueueLast = null; - var update = first; - - do { - // An extra OffscreenLane bit is added to updates that were made to - // a hidden tree, so that we can distinguish them from updates that were - // already there when the tree was hidden. - var updateLane = removeLanes(update.lane, OffscreenLane); - var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then - // it's not a "base" update and we should disregard the extra base lanes - // that were added to renderLanes when we entered the Offscreen tree. - - var shouldSkipUpdate = isHiddenUpdate - ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) - : !isSubsetOfLanes(renderLanes, updateLane); - - if (shouldSkipUpdate) { - // Priority is insufficient. Skip this update. If this is the first - // skipped update, the previous update/state is the new base - // update/state. - var clone = { - lane: updateLane, - revertLane: update.revertLane, - action: update.action, - hasEagerState: update.hasEagerState, - eagerState: update.eagerState, - next: null - }; + function checkClassInstance(workInProgress, ctor, newProps) { + var instance = workInProgress.stateNode; - if (newBaseQueueLast === null) { - newBaseQueueFirst = newBaseQueueLast = clone; - newBaseState = newState; - } else { - newBaseQueueLast = newBaseQueueLast.next = clone; - } // Update the remaining priority in the queue. - // TODO: Don't need to accumulate this. Instead, we can remove - // renderLanes from the original lanes. + { + var name = getComponentNameFromType(ctor) || "Component"; + var renderPresent = instance.render; - currentlyRenderingFiber$1.lanes = mergeLanes( - currentlyRenderingFiber$1.lanes, - updateLane - ); - markSkippedUpdateLanes(updateLane); - } else { - // This update does have sufficient priority. - // Check if this is an optimistic update. - var revertLane = update.revertLane; - - if (!enableAsyncActions || revertLane === NoLane) { - // This is not an optimistic update, and we're going to apply it now. - // But, if there were earlier updates that were skipped, we need to - // leave this update in the queue so it can be rebased later. - if (newBaseQueueLast !== null) { - var _clone = { - // This update is going to be committed so we never want uncommit - // it. Using NoLane works because 0 is a subset of all bitmasks, so - // this will never be skipped by the check above. - lane: NoLane, - revertLane: NoLane, - action: update.action, - hasEagerState: update.hasEagerState, - eagerState: update.eagerState, - next: null - }; - newBaseQueueLast = newBaseQueueLast.next = _clone; - } - } else { - // This is an optimistic update. If the "revert" priority is - // sufficient, don't apply the update. Otherwise, apply the update, - // but leave it in the queue so it can be either reverted or - // rebased in a subsequent render. - if (isSubsetOfLanes(renderLanes, revertLane)) { - // The transition that this optimistic update is associated with - // has finished. Pretend the update doesn't exist by skipping - // over it. - update = update.next; - continue; + if (!renderPresent) { + if (ctor.prototype && typeof ctor.prototype.render === "function") { + error( + "%s(...): No `render` method found on the returned component " + + "instance: did you accidentally return an object from the constructor?", + name + ); } else { - var _clone2 = { - // Once we commit an optimistic update, we shouldn't uncommit it - // until the transition it is associated with has finished - // (represented by revertLane). Using NoLane here works because 0 - // is a subset of all bitmasks, so this will never be skipped by - // the check above. - lane: NoLane, - // Reuse the same revertLane so we know when the transition - // has finished. - revertLane: update.revertLane, - action: update.action, - hasEagerState: update.hasEagerState, - eagerState: update.eagerState, - next: null - }; - - if (newBaseQueueLast === null) { - newBaseQueueFirst = newBaseQueueLast = _clone2; - newBaseState = newState; - } else { - newBaseQueueLast = newBaseQueueLast.next = _clone2; - } // Update the remaining priority in the queue. - // TODO: Don't need to accumulate this. Instead, we can remove - // renderLanes from the original lanes. - - currentlyRenderingFiber$1.lanes = mergeLanes( - currentlyRenderingFiber$1.lanes, - revertLane + error( + "%s(...): No `render` method found on the returned component " + + "instance: you may have forgotten to define `render`.", + name ); - markSkippedUpdateLanes(revertLane); } - } // Process this update. + } - var action = update.action; + if ( + instance.getInitialState && + !instance.getInitialState.isReactClassApproved && + !instance.state + ) { + 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 + ); + } - if (shouldDoubleInvokeUserFnsInHooksDEV) { - reducer(newState, action); + if ( + instance.getDefaultProps && + !instance.getDefaultProps.isReactClassApproved + ) { + 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 + ); } - if (update.hasEagerState) { - // If this update is a state update (not a reducer) and was processed eagerly, - // we can use the eagerly computed state - newState = update.eagerState; - } else { - newState = reducer(newState, action); + if (instance.propTypes) { + error( + "propTypes was defined as an instance property on %s. Use a static " + + "property to define propTypes instead.", + name + ); } - } - update = update.next; - } while (update !== null && update !== first); + if (instance.contextType) { + error( + "contextType was defined as an instance property on %s. Use a static " + + "property to define contextType instead.", + name + ); + } - if (newBaseQueueLast === null) { - newBaseState = newState; - } else { - newBaseQueueLast.next = newBaseQueueFirst; - } // Mark that the fiber performed work, but only if the new state is - // different from the current state. + { + if (instance.contextTypes) { + error( + "contextTypes was defined as an instance property on %s. Use a static " + + "property to define contextTypes instead.", + name + ); + } - if (!objectIs(newState, hook.memoizedState)) { - markWorkInProgressReceivedUpdate(); - } + if ( + ctor.contextType && + ctor.contextTypes && + !didWarnAboutContextTypeAndContextTypes.has(ctor) + ) { + didWarnAboutContextTypeAndContextTypes.add(ctor); - hook.memoizedState = newState; - hook.baseState = newBaseState; - hook.baseQueue = newBaseQueueLast; - queue.lastRenderedState = newState; - } + error( + "%s declares both contextTypes and contextType static properties. " + + "The legacy contextTypes property will be ignored.", + name + ); + } + } - if (baseQueue === null) { - // `queue.lanes` is used for entangling transitions. We can set it back to - // zero once the queue is empty. - queue.lanes = NoLanes; - } + if (typeof instance.componentShouldUpdate === "function") { + 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 + ); + } - var dispatch = queue.dispatch; - return [hook.memoizedState, dispatch]; -} + if ( + ctor.prototype && + ctor.prototype.isPureReactComponent && + typeof instance.shouldComponentUpdate !== "undefined" + ) { + 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" + ); + } -function rerenderReducer(reducer, initialArg, init) { - var hook = updateWorkInProgressHook(); - var queue = hook.queue; + if (typeof instance.componentDidUnmount === "function") { + error( + "%s has a method called " + + "componentDidUnmount(). But there is no such lifecycle method. " + + "Did you mean componentWillUnmount()?", + name + ); + } - if (queue === null) { - throw new Error( - "Should have a queue. This is likely a bug in React. Please file an issue." - ); - } + if (typeof instance.componentDidReceiveProps === "function") { + 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 + ); + } - queue.lastRenderedReducer = reducer; // This is a re-render. Apply the new render phase updates to the previous - // work-in-progress hook. + if (typeof instance.componentWillRecieveProps === "function") { + error( + "%s has a method called " + + "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", + name + ); + } - var dispatch = queue.dispatch; - var lastRenderPhaseUpdate = queue.pending; - var newState = hook.memoizedState; + if (typeof instance.UNSAFE_componentWillRecieveProps === "function") { + error( + "%s has a method called " + + "UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?", + name + ); + } - if (lastRenderPhaseUpdate !== null) { - // The queue doesn't persist past this render pass. - queue.pending = null; - var firstRenderPhaseUpdate = lastRenderPhaseUpdate.next; - var update = firstRenderPhaseUpdate; + var hasMutatedProps = instance.props !== newProps; - do { - // Process this render phase update. We don't have to check the - // priority because it will always be the same as the current - // render's. - var action = update.action; - newState = reducer(newState, action); - update = update.next; - } while (update !== firstRenderPhaseUpdate); // Mark that the fiber performed work, but only if the new state is - // different from the current state. + if (instance.props !== undefined && hasMutatedProps) { + error( + "%s(...): When calling super() in `%s`, make sure to pass " + + "up the same props that your component's constructor was passed.", + name, + name + ); + } - if (!objectIs(newState, hook.memoizedState)) { - markWorkInProgressReceivedUpdate(); - } + if (instance.defaultProps) { + 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 + ); + } - hook.memoizedState = newState; // Don't persist the state accumulated from the render phase updates to - // the base state unless the queue is empty. - // TODO: Not sure if this is the desired semantics, but it's what we - // do for gDSFP. I can't remember why. + if ( + typeof instance.getSnapshotBeforeUpdate === "function" && + typeof instance.componentDidUpdate !== "function" && + !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor) + ) { + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor); - if (hook.baseQueue === null) { - hook.baseState = newState; - } + error( + "%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). " + + "This component defines getSnapshotBeforeUpdate() only.", + getComponentNameFromType(ctor) + ); + } - queue.lastRenderedState = newState; - } + if (typeof instance.getDerivedStateFromProps === "function") { + error( + "%s: getDerivedStateFromProps() is defined as an instance method " + + "and will be ignored. Instead, declare it as a static method.", + name + ); + } - return [newState, dispatch]; -} + if (typeof instance.getDerivedStateFromError === "function") { + error( + "%s: getDerivedStateFromError() is defined as an instance method " + + "and will be ignored. Instead, declare it as a static method.", + name + ); + } -function mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { - var fiber = currentlyRenderingFiber$1; - var hook = mountWorkInProgressHook(); - var nextSnapshot; + if (typeof ctor.getSnapshotBeforeUpdate === "function") { + error( + "%s: getSnapshotBeforeUpdate() is defined as a static method " + + "and will be ignored. Instead, declare it as an instance method.", + name + ); + } - { - nextSnapshot = getSnapshot(); + var state = instance.state; - { - if (!didWarnUncachedGetSnapshot) { - var cachedSnapshot = getSnapshot(); + if (state && (typeof state !== "object" || isArray(state))) { + error("%s.state: must be set to an object or null", name); + } - if (!objectIs(nextSnapshot, cachedSnapshot)) { + if ( + typeof instance.getChildContext === "function" && + typeof ctor.childContextTypes !== "object" + ) { error( - "The result of getSnapshot should be cached to avoid an infinite loop" + "%s.getChildContext(): childContextTypes must be defined in order to " + + "use getChildContext().", + name ); - - didWarnUncachedGetSnapshot = true; } } - } // Unless we're rendering a blocking lane, schedule a consistency check. - // Right before committing, we will walk the tree and check if any of the - // stores were mutated. - // - // We won't do this if we're hydrating server-rendered content, because if - // the content is stale, it's already visible anyway. Instead we'll patch - // it up in a passive effect. + } - var root = getWorkInProgressRoot(); + function adoptClassInstance(workInProgress, instance) { + instance.updater = classComponentUpdater; + workInProgress.stateNode = instance; // The instance needs access to the fiber so that it can schedule updates - if (root === null) { - throw new Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." - ); + set(instance, workInProgress); + + { + instance._reactInternalInstance = fakeInternalInstance; + } } - var rootRenderLanes = getWorkInProgressRootRenderLanes(); - - if (!includesBlockingLane(root, rootRenderLanes)) { - pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); - } - } // Read the current snapshot from the store on every render. This breaks the - // normal rules of React, and only works because store updates are - // always synchronous. - - hook.memoizedState = nextSnapshot; - var inst = { - value: nextSnapshot, - getSnapshot: getSnapshot - }; - hook.queue = inst; // Schedule an effect to subscribe to the store. - - mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]); // Schedule an effect to update the mutable instance fields. We will update - // this whenever subscribe, getSnapshot, or value changes. Because there's no - // clean-up function, and we track the deps correctly, we can call pushEffect - // directly, without storing any additional state. For the same reason, we - // don't need to set a static flag, either. - - fiber.flags |= Passive$1; - pushEffect( - HasEffect | Passive, - updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), - createEffectInstance(), - null - ); - return nextSnapshot; -} + function constructClassInstance(workInProgress, ctor, props) { + var isLegacyContextConsumer = false; + var unmaskedContext = emptyContextObject; + var context = emptyContextObject; + var contextType = ctor.contextType; -function updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { - var fiber = currentlyRenderingFiber$1; - var hook = updateWorkInProgressHook(); // Read the current snapshot from the store on every render. This breaks the - // normal rules of React, and only works because store updates are - // always synchronous. + { + if ("contextType" in ctor) { + var isValid = // Allow null for conditional declaration + contextType === null || + (contextType !== undefined && + contextType.$$typeof === REACT_CONTEXT_TYPE && + contextType._context === undefined); // Not a + + if (!isValid && !didWarnAboutInvalidateContextType.has(ctor)) { + didWarnAboutInvalidateContextType.add(ctor); + var addendum = ""; + + if (contextType === undefined) { + 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."; + } else if (typeof contextType !== "object") { + addendum = " However, it is set to a " + typeof contextType + "."; + } else if (contextType.$$typeof === REACT_PROVIDER_TYPE) { + addendum = + " Did you accidentally pass the Context.Provider instead?"; + } else if (contextType._context !== undefined) { + // + addendum = + " Did you accidentally pass the Context.Consumer instead?"; + } else { + addendum = + " However, it is set to an object with keys {" + + Object.keys(contextType).join(", ") + + "}."; + } - var nextSnapshot; + error( + "%s defines an invalid contextType. " + + "contextType should point to the Context object returned by React.createContext().%s", + getComponentNameFromType(ctor) || "Component", + addendum + ); + } + } + } - { - nextSnapshot = getSnapshot(); + if (typeof contextType === "object" && contextType !== null) { + context = readContext(contextType); + } else { + unmaskedContext = getUnmaskedContext(workInProgress, ctor, true); + var contextTypes = ctor.contextTypes; + isLegacyContextConsumer = + contextTypes !== null && contextTypes !== undefined; + context = isLegacyContextConsumer + ? getMaskedContext(workInProgress, unmaskedContext) + : emptyContextObject; + } - { - if (!didWarnUncachedGetSnapshot) { - var cachedSnapshot = getSnapshot(); + var instance = new ctor(props, context); // Instantiate twice to help detect side-effects. - if (!objectIs(nextSnapshot, cachedSnapshot)) { - error( - "The result of getSnapshot should be cached to avoid an infinite loop" - ); + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); - didWarnUncachedGetSnapshot = true; + try { + instance = new ctor(props, context); // eslint-disable-line no-new + } finally { + setIsStrictModeForDevtools(false); + } } } - } - } - var prevSnapshot = (currentHook || hook).memoizedState; - var snapshotChanged = !objectIs(prevSnapshot, nextSnapshot); + var state = (workInProgress.memoizedState = + instance.state !== null && instance.state !== undefined + ? instance.state + : null); + adoptClassInstance(workInProgress, instance); + + { + if ( + typeof ctor.getDerivedStateFromProps === "function" && + state === null + ) { + var componentName = getComponentNameFromType(ctor) || "Component"; + + if (!didWarnAboutUninitializedState.has(componentName)) { + didWarnAboutUninitializedState.add(componentName); - if (snapshotChanged) { - hook.memoizedState = nextSnapshot; - markWorkInProgressReceivedUpdate(); - } + 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 + ); + } + } // If new component APIs are defined, "unsafe" lifecycles won't be called. + // Warn about these lifecycles if they are present. + // Don't warn about react-lifecycles-compat polyfilled methods though. - var inst = hook.queue; - updateEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [ - subscribe - ]); // Whenever getSnapshot or subscribe changes, we need to check in the - // commit phase if there was an interleaved mutation. In concurrent mode - // this can happen all the time, but even in synchronous mode, an earlier - // effect may have mutated the store. + if ( + typeof ctor.getDerivedStateFromProps === "function" || + typeof instance.getSnapshotBeforeUpdate === "function" + ) { + var foundWillMountName = null; + var foundWillReceivePropsName = null; + var foundWillUpdateName = null; - if ( - inst.getSnapshot !== getSnapshot || - snapshotChanged || // Check if the subscribe function changed. We can save some memory by - // checking whether we scheduled a subscription effect above. - (workInProgressHook !== null && - workInProgressHook.memoizedState.tag & HasEffect) - ) { - fiber.flags |= Passive$1; - pushEffect( - HasEffect | Passive, - updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), - createEffectInstance(), - null - ); // Unless we're rendering a blocking lane, schedule a consistency check. - // Right before committing, we will walk the tree and check if any of the - // stores were mutated. + if ( + typeof instance.componentWillMount === "function" && + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + foundWillMountName = "componentWillMount"; + } else if (typeof instance.UNSAFE_componentWillMount === "function") { + foundWillMountName = "UNSAFE_componentWillMount"; + } - var root = getWorkInProgressRoot(); + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== + true + ) { + foundWillReceivePropsName = "componentWillReceiveProps"; + } else if ( + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + foundWillReceivePropsName = "UNSAFE_componentWillReceiveProps"; + } - if (root === null) { - throw new Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." - ); - } + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + foundWillUpdateName = "componentWillUpdate"; + } else if ( + typeof instance.UNSAFE_componentWillUpdate === "function" + ) { + foundWillUpdateName = "UNSAFE_componentWillUpdate"; + } - if (!includesBlockingLane(root, renderLanes)) { - pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); - } - } + if ( + foundWillMountName !== null || + foundWillReceivePropsName !== null || + foundWillUpdateName !== null + ) { + var _componentName = getComponentNameFromType(ctor) || "Component"; - return nextSnapshot; -} + var newApiName = + typeof ctor.getDerivedStateFromProps === "function" + ? "getDerivedStateFromProps()" + : "getSnapshotBeforeUpdate()"; -function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) { - fiber.flags |= StoreConsistency; - var check = { - getSnapshot: getSnapshot, - value: renderedSnapshot - }; - var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; - - if (componentUpdateQueue === null) { - componentUpdateQueue = createFunctionComponentUpdateQueue(); - currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; - componentUpdateQueue.stores = [check]; - } else { - var stores = componentUpdateQueue.stores; - - if (stores === null) { - componentUpdateQueue.stores = [check]; - } else { - stores.push(check); + if ( + !didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName) + ) { + didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName); + + 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 : "" + ); + } + } + } + } // Cache unmasked context so we can avoid recreating masked context unless necessary. + // ReactFiberContext usually updates this cache but can't for newly-created instances. + + if (isLegacyContextConsumer) { + cacheContext(workInProgress, unmaskedContext, context); + } + + return instance; } - } -} -function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) { - // These are updated in the passive phase - inst.value = nextSnapshot; - inst.getSnapshot = getSnapshot; // Something may have been mutated in between render and commit. This could - // have been in an event that fired before the passive effects, or it could - // have been in a layout effect. In that case, we would have used the old - // snapsho and getSnapshot values to bail out. We need to check one more time. - - if (checkIfSnapshotChanged(inst)) { - // Force a re-render. - forceStoreRerender(fiber); - } -} + function callComponentWillMount(workInProgress, instance) { + var oldState = instance.state; + + if (typeof instance.componentWillMount === "function") { + instance.componentWillMount(); + } + + if (typeof instance.UNSAFE_componentWillMount === "function") { + instance.UNSAFE_componentWillMount(); + } + + if (oldState !== instance.state) { + { + error( + "%s.componentWillMount(): Assigning directly to this.state is " + + "deprecated (except inside a component's " + + "constructor). Use setState instead.", + getComponentNameFromFiber(workInProgress) || "Component" + ); + } -function subscribeToStore(fiber, inst, subscribe) { - var handleStoreChange = function () { - // The store changed. Check if the snapshot changed since the last time we - // read from the store. - if (checkIfSnapshotChanged(inst)) { - // Force a re-render. - forceStoreRerender(fiber); + classComponentUpdater.enqueueReplaceState( + instance, + instance.state, + null + ); + } } - }; // Subscribe to the store and return a clean-up function. - return subscribe(handleStoreChange); -} + function callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + nextContext + ) { + var oldState = instance.state; -function checkIfSnapshotChanged(inst) { - var latestGetSnapshot = inst.getSnapshot; - var prevValue = inst.value; + if (typeof instance.componentWillReceiveProps === "function") { + instance.componentWillReceiveProps(newProps, nextContext); + } - try { - var nextValue = latestGetSnapshot(); - return !objectIs(prevValue, nextValue); - } catch (error) { - return true; - } -} + if (typeof instance.UNSAFE_componentWillReceiveProps === "function") { + instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); + } -function forceStoreRerender(fiber) { - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + if (instance.state !== oldState) { + { + var componentName = + getComponentNameFromFiber(workInProgress) || "Component"; - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } -} + if (!didWarnAboutStateAssignmentForComponent.has(componentName)) { + didWarnAboutStateAssignmentForComponent.add(componentName); -function mountStateImpl(initialState) { - var hook = mountWorkInProgressHook(); - - if (typeof initialState === "function") { - // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types - initialState = initialState(); - } - - hook.memoizedState = hook.baseState = initialState; - var queue = { - pending: null, - lanes: NoLanes, - dispatch: null, - lastRenderedReducer: basicStateReducer, - lastRenderedState: initialState - }; - hook.queue = queue; - return hook; -} + error( + "%s.componentWillReceiveProps(): Assigning directly to " + + "this.state is deprecated (except inside a component's " + + "constructor). Use setState instead.", + componentName + ); + } + } -function mountState(initialState) { - var hook = mountStateImpl(initialState); - var queue = hook.queue; - var dispatch = dispatchSetState.bind(null, currentlyRenderingFiber$1, queue); - queue.dispatch = dispatch; - return [hook.memoizedState, dispatch]; -} + classComponentUpdater.enqueueReplaceState( + instance, + instance.state, + null + ); + } + } // Invokes the mount life-cycles on a previously never rendered instance. -function updateState(initialState) { - return updateReducer(basicStateReducer); -} + function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { + { + checkClassInstance(workInProgress, ctor, newProps); + } -function rerenderState(initialState) { - return rerenderReducer(basicStateReducer); -} + var instance = workInProgress.stateNode; + instance.props = newProps; + instance.state = workInProgress.memoizedState; + instance.refs = {}; + initializeUpdateQueue(workInProgress); + var contextType = ctor.contextType; -function mountOptimistic(passthrough, reducer) { - var hook = mountWorkInProgressHook(); - hook.memoizedState = hook.baseState = passthrough; - var queue = { - pending: null, - lanes: NoLanes, - dispatch: null, - // Optimistic state does not use the eager update optimization. - lastRenderedReducer: null, - lastRenderedState: null - }; - hook.queue = queue; // This is different than the normal setState function. - - var dispatch = dispatchOptimisticSetState.bind( - null, - currentlyRenderingFiber$1, - true, - queue - ); - queue.dispatch = dispatch; - return [passthrough, dispatch]; -} + if (typeof contextType === "object" && contextType !== null) { + instance.context = readContext(contextType); + } else { + var unmaskedContext = getUnmaskedContext(workInProgress, ctor, true); + instance.context = getMaskedContext(workInProgress, unmaskedContext); + } -function updateOptimistic(passthrough, reducer) { - var hook = updateWorkInProgressHook(); - return updateOptimisticImpl(hook, currentHook, passthrough, reducer); -} + { + if (instance.state === newProps) { + var componentName = getComponentNameFromType(ctor) || "Component"; -function updateOptimisticImpl(hook, current, passthrough, reducer) { - // Optimistic updates are always rebased on top of the latest value passed in - // as an argument. It's called a passthrough because if there are no pending - // updates, it will be returned as-is. - // - // Reset the base state to the passthrough. Future updates will be applied - // on top of this. - hook.baseState = passthrough; // If a reducer is not provided, default to the same one used by useState. - - var resolvedReducer = - typeof reducer === "function" ? reducer : basicStateReducer; - return updateReducerImpl(hook, currentHook, resolvedReducer); -} + if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) { + didWarnAboutDirectlyAssigningPropsToState.add(componentName); -function rerenderOptimistic(passthrough, reducer) { - // Unlike useState, useOptimistic doesn't support render phase updates. - // Also unlike useState, we need to replay all pending updates again in case - // the passthrough value changed. - // - // So instead of a forked re-render implementation that knows how to handle - // render phase udpates, we can use the same implementation as during a - // regular mount or update. - var hook = updateWorkInProgressHook(); - - if (currentHook !== null) { - // This is an update. Process the update queue. - return updateOptimisticImpl(hook, currentHook, passthrough, reducer); - } // This is a mount. No updates to process. - // Reset the base state to the passthrough. Future updates will be applied - // on top of this. - - hook.baseState = passthrough; - var dispatch = hook.queue.dispatch; - return [passthrough, dispatch]; -} // useFormState actions run sequentially, because each action receives the - -function pushEffect(tag, create, inst, deps) { - var effect = { - tag: tag, - create: create, - inst: inst, - deps: deps, - // Circular - next: null - }; - var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; - - if (componentUpdateQueue === null) { - componentUpdateQueue = createFunctionComponentUpdateQueue(); - currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; - componentUpdateQueue.lastEffect = effect.next = effect; - } else { - var lastEffect = componentUpdateQueue.lastEffect; - - if (lastEffect === null) { - componentUpdateQueue.lastEffect = effect.next = effect; - } else { - var firstEffect = lastEffect.next; - lastEffect.next = effect; - effect.next = firstEffect; - componentUpdateQueue.lastEffect = effect; - } - } + 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 + ); + } + } - return effect; -} + if (workInProgress.mode & StrictLegacyMode) { + ReactStrictModeWarnings.recordLegacyContextWarning( + workInProgress, + instance + ); + } -function createEffectInstance() { - return { - destroy: undefined - }; -} + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings( + workInProgress, + instance + ); + } -var stackContainsErrorMessage = null; + instance.state = workInProgress.memoizedState; + var getDerivedStateFromProps = ctor.getDerivedStateFromProps; -function getCallerStackFrame() { - // eslint-disable-next-line react-internal/prod-error-codes - var stackFrames = new Error("Error message").stack.split("\n"); // Some browsers (e.g. Chrome) include the error message in the stack - // but others (e.g. Firefox) do not. + if (typeof getDerivedStateFromProps === "function") { + applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + newProps + ); + instance.state = workInProgress.memoizedState; + } // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. - if (stackContainsErrorMessage === null) { - stackContainsErrorMessage = stackFrames[0].includes("Error message"); - } + if ( + typeof ctor.getDerivedStateFromProps !== "function" && + typeof instance.getSnapshotBeforeUpdate !== "function" && + (typeof instance.UNSAFE_componentWillMount === "function" || + typeof instance.componentWillMount === "function") + ) { + callComponentWillMount(workInProgress, instance); // If we had additional state updates during this life-cycle, let's + // process them now. - return stackContainsErrorMessage - ? stackFrames.slice(3, 4).join("\n") - : stackFrames.slice(2, 3).join("\n"); -} + processUpdateQueue(workInProgress, newProps, instance, renderLanes); + instance.state = workInProgress.memoizedState; + } -function mountRef(initialValue) { - var hook = mountWorkInProgressHook(); + if (typeof instance.componentDidMount === "function") { + workInProgress.flags |= Update | LayoutStatic; + } - if (enableUseRefAccessWarning) { - { - // Support lazy initialization pattern shown in docs. - // We need to store the caller stack frame so that we don't warn on subsequent renders. - var hasBeenInitialized = initialValue != null; - var lazyInitGetterStack = null; - var didCheckForLazyInit = false; // Only warn once per component+hook. - - var didWarnAboutRead = false; - var didWarnAboutWrite = false; - var current = initialValue; - var ref = { - get current() { - if (!hasBeenInitialized) { - didCheckForLazyInit = true; - lazyInitGetterStack = getCallerStackFrame(); - } else if (currentlyRenderingFiber$1 !== null && !didWarnAboutRead) { - if ( - lazyInitGetterStack === null || - lazyInitGetterStack !== getCallerStackFrame() - ) { - didWarnAboutRead = true; + if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { + workInProgress.flags |= MountLayoutDev; + } + } - warn( - "%s: Unsafe read of a mutable value during render.\n\n" + - "Reading from a ref during render is only safe if:\n" + - "1. The ref value has not been updated, or\n" + - "2. The ref holds a lazily-initialized value that is only set once.\n", - getComponentNameFromFiber(currentlyRenderingFiber$1) || - "Unknown" - ); - } - } + function resumeMountClassInstance( + workInProgress, + ctor, + newProps, + renderLanes + ) { + var instance = workInProgress.stateNode; + var oldProps = workInProgress.memoizedProps; + instance.props = oldProps; + var oldContext = instance.context; + var contextType = ctor.contextType; + var nextContext = emptyContextObject; + + if (typeof contextType === "object" && contextType !== null) { + nextContext = readContext(contextType); + } else { + var nextLegacyUnmaskedContext = getUnmaskedContext( + workInProgress, + ctor, + true + ); + nextContext = getMaskedContext( + workInProgress, + nextLegacyUnmaskedContext + ); + } - return current; - }, + var getDerivedStateFromProps = ctor.getDerivedStateFromProps; + var hasNewLifecycles = + typeof getDerivedStateFromProps === "function" || + typeof instance.getSnapshotBeforeUpdate === "function"; // Note: During these life-cycles, instance.props/instance.state are what + // ever the previously attempted to render - not the "current". However, + // during componentDidUpdate we pass the "current" props. + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. - set current(value) { - if (currentlyRenderingFiber$1 !== null && !didWarnAboutWrite) { - if (hasBeenInitialized || !didCheckForLazyInit) { - didWarnAboutWrite = true; + if ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillReceiveProps === "function" || + typeof instance.componentWillReceiveProps === "function") + ) { + if (oldProps !== newProps || oldContext !== nextContext) { + callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + nextContext + ); + } + } - warn( - "%s: Unsafe write of a mutable value during render.\n\n" + - "Writing to a ref during render is only safe if the ref holds " + - "a lazily-initialized value that is only set once.\n", - getComponentNameFromFiber(currentlyRenderingFiber$1) || - "Unknown" - ); - } - } + resetHasForceUpdateBeforeProcessing(); + var oldState = workInProgress.memoizedState; + var newState = (instance.state = oldState); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); + newState = workInProgress.memoizedState; - hasBeenInitialized = true; - current = value; + if ( + oldProps === newProps && + oldState === newState && + !hasContextChanged() && + !checkHasForceUpdateAfterProcessing() + ) { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidMount === "function") { + workInProgress.flags |= Update | LayoutStatic; } - }; - Object.seal(ref); - hook.memoizedState = ref; - return ref; - } - } else { - var _ref2 = { - current: initialValue - }; - hook.memoizedState = _ref2; - return _ref2; - } -} -function updateRef(initialValue) { - var hook = updateWorkInProgressHook(); - return hook.memoizedState; -} + if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { + workInProgress.flags |= MountLayoutDev; + } -function mountEffectImpl(fiberFlags, hookFlags, create, deps) { - var hook = mountWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - currentlyRenderingFiber$1.flags |= fiberFlags; - hook.memoizedState = pushEffect( - HasEffect | hookFlags, - create, - createEffectInstance(), - nextDeps - ); -} + return false; + } -function updateEffectImpl(fiberFlags, hookFlags, create, deps) { - var hook = updateWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var effect = hook.memoizedState; - var inst = effect.inst; // currentHook is null on initial mount when rerendering after a render phase - // state update or for strict mode. + if (typeof getDerivedStateFromProps === "function") { + applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + newProps + ); + newState = workInProgress.memoizedState; + } - if (currentHook !== null) { - if (nextDeps !== null) { - var prevEffect = currentHook.memoizedState; - var prevDeps = prevEffect.deps; + var shouldUpdate = + checkHasForceUpdateAfterProcessing() || + checkShouldComponentUpdate( + workInProgress, + ctor, + oldProps, + newProps, + oldState, + newState, + nextContext + ); - if (areHookInputsEqual(nextDeps, prevDeps)) { - hook.memoizedState = pushEffect(hookFlags, create, inst, nextDeps); - return; - } - } - } + if (shouldUpdate) { + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. + if ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillMount === "function" || + typeof instance.componentWillMount === "function") + ) { + if (typeof instance.componentWillMount === "function") { + instance.componentWillMount(); + } - currentlyRenderingFiber$1.flags |= fiberFlags; - hook.memoizedState = pushEffect( - HasEffect | hookFlags, - create, - inst, - nextDeps - ); -} + if (typeof instance.UNSAFE_componentWillMount === "function") { + instance.UNSAFE_componentWillMount(); + } + } -function mountEffect(create, deps) { - if ( - (currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode && - (currentlyRenderingFiber$1.mode & NoStrictPassiveEffectsMode) === NoMode - ) { - mountEffectImpl( - MountPassiveDev | Passive$1 | PassiveStatic, - Passive, - create, - deps - ); - } else { - mountEffectImpl(Passive$1 | PassiveStatic, Passive, create, deps); - } -} + if (typeof instance.componentDidMount === "function") { + workInProgress.flags |= Update | LayoutStatic; + } -function updateEffect(create, deps) { - updateEffectImpl(Passive$1, Passive, create, deps); -} + if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { + workInProgress.flags |= MountLayoutDev; + } + } else { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidMount === "function") { + workInProgress.flags |= Update | LayoutStatic; + } -function useEffectEventImpl(payload) { - currentlyRenderingFiber$1.flags |= Update; - var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; + if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { + workInProgress.flags |= MountLayoutDev; + } // If shouldComponentUpdate returned false, we should still update the + // memoized state to indicate that this work can be reused. - if (componentUpdateQueue === null) { - componentUpdateQueue = createFunctionComponentUpdateQueue(); - currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; - componentUpdateQueue.events = [payload]; - } else { - var events = componentUpdateQueue.events; + workInProgress.memoizedProps = newProps; + workInProgress.memoizedState = newState; + } // Update the existing instance's state, props, and context pointers even + // if shouldComponentUpdate returns false. - if (events === null) { - componentUpdateQueue.events = [payload]; - } else { - events.push(payload); - } - } -} + instance.props = newProps; + instance.state = newState; + instance.context = nextContext; + return shouldUpdate; + } // Invokes the update life-cycles and returns false if it shouldn't rerender. -function mountEvent(callback) { - var hook = mountWorkInProgressHook(); - var ref = { - impl: callback - }; - hook.memoizedState = ref; // $FlowIgnore[incompatible-return] + function updateClassInstance( + current, + workInProgress, + ctor, + newProps, + renderLanes + ) { + var instance = workInProgress.stateNode; + cloneUpdateQueue(current, workInProgress); + var unresolvedOldProps = workInProgress.memoizedProps; + var oldProps = + workInProgress.type === workInProgress.elementType + ? unresolvedOldProps + : resolveDefaultProps(workInProgress.type, unresolvedOldProps); + instance.props = oldProps; + var unresolvedNewProps = workInProgress.pendingProps; + var oldContext = instance.context; + var contextType = ctor.contextType; + var nextContext = emptyContextObject; + + if (typeof contextType === "object" && contextType !== null) { + nextContext = readContext(contextType); + } else { + var nextUnmaskedContext = getUnmaskedContext( + workInProgress, + ctor, + true + ); + nextContext = getMaskedContext(workInProgress, nextUnmaskedContext); + } - return function eventFn() { - if (isInvalidExecutionContextForEventFunction()) { - throw new Error( - "A function wrapped in useEffectEvent can't be called during rendering." - ); - } + var getDerivedStateFromProps = ctor.getDerivedStateFromProps; + var hasNewLifecycles = + typeof getDerivedStateFromProps === "function" || + typeof instance.getSnapshotBeforeUpdate === "function"; // Note: During these life-cycles, instance.props/instance.state are what + // ever the previously attempted to render - not the "current". However, + // during componentDidUpdate we pass the "current" props. + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. - return ref.impl.apply(undefined, arguments); - }; -} + if ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillReceiveProps === "function" || + typeof instance.componentWillReceiveProps === "function") + ) { + if ( + unresolvedOldProps !== unresolvedNewProps || + oldContext !== nextContext + ) { + callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + nextContext + ); + } + } -function updateEvent(callback) { - var hook = updateWorkInProgressHook(); - var ref = hook.memoizedState; - useEffectEventImpl({ - ref: ref, - nextImpl: callback - }); // $FlowIgnore[incompatible-return] + resetHasForceUpdateBeforeProcessing(); + var oldState = workInProgress.memoizedState; + var newState = (instance.state = oldState); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); + newState = workInProgress.memoizedState; - return function eventFn() { - if (isInvalidExecutionContextForEventFunction()) { - throw new Error( - "A function wrapped in useEffectEvent can't be called during rendering." - ); - } + if ( + unresolvedOldProps === unresolvedNewProps && + oldState === newState && + !hasContextChanged() && + !checkHasForceUpdateAfterProcessing() && + !( + enableLazyContextPropagation && + current !== null && + current.dependencies !== null && + checkIfContextChanged(current.dependencies) + ) + ) { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidUpdate === "function") { + if ( + unresolvedOldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.flags |= Update; + } + } - return ref.impl.apply(undefined, arguments); - }; -} + if (typeof instance.getSnapshotBeforeUpdate === "function") { + if ( + unresolvedOldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.flags |= Snapshot; + } + } -function mountInsertionEffect(create, deps) { - mountEffectImpl(Update, Insertion, create, deps); -} + return false; + } -function updateInsertionEffect(create, deps) { - return updateEffectImpl(Update, Insertion, create, deps); -} + if (typeof getDerivedStateFromProps === "function") { + applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + newProps + ); + newState = workInProgress.memoizedState; + } -function mountLayoutEffect(create, deps) { - var fiberFlags = Update | LayoutStatic; + 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, + // both before and after `shouldComponentUpdate` has been called. Not ideal, + // but I'm loath to refactor this function. This only happens for memoized + // components so it's not that common. + (enableLazyContextPropagation && + current !== null && + current.dependencies !== null && + checkIfContextChanged(current.dependencies)); - if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { - fiberFlags |= MountLayoutDev; - } + if (shouldUpdate) { + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. + if ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillUpdate === "function" || + typeof instance.componentWillUpdate === "function") + ) { + if (typeof instance.componentWillUpdate === "function") { + instance.componentWillUpdate(newProps, newState, nextContext); + } - return mountEffectImpl(fiberFlags, Layout, create, deps); -} + if (typeof instance.UNSAFE_componentWillUpdate === "function") { + instance.UNSAFE_componentWillUpdate( + newProps, + newState, + nextContext + ); + } + } -function updateLayoutEffect(create, deps) { - return updateEffectImpl(Update, Layout, create, deps); -} + if (typeof instance.componentDidUpdate === "function") { + workInProgress.flags |= Update; + } -function imperativeHandleEffect(create, ref) { - if (typeof ref === "function") { - var refCallback = ref; - var inst = create(); - refCallback(inst); - return function () { - refCallback(null); - }; - } else if (ref !== null && ref !== undefined) { - var refObject = ref; + if (typeof instance.getSnapshotBeforeUpdate === "function") { + workInProgress.flags |= Snapshot; + } + } else { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidUpdate === "function") { + if ( + unresolvedOldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.flags |= Update; + } + } - { - if (!refObject.hasOwnProperty("current")) { - 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(", ") + "}" - ); - } + if (typeof instance.getSnapshotBeforeUpdate === "function") { + if ( + unresolvedOldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.flags |= Snapshot; + } + } // If shouldComponentUpdate returned false, we should still update the + // memoized props/state to indicate that this work can be reused. + + workInProgress.memoizedProps = newProps; + workInProgress.memoizedState = newState; + } // Update the existing instance's state, props, and context pointers even + // if shouldComponentUpdate returns false. + + instance.props = newProps; + instance.state = newState; + instance.context = nextContext; + return shouldUpdate; + } + + function createCapturedValueAtFiber(value, source) { + // If the value is an error, call this function immediately after it is thrown + // so the stack is accurate. + return { + value: value, + source: source, + stack: getStackByFiberInDevAndProd(source), + digest: null + }; + } + function createCapturedValue(value, digest, stack) { + return { + value: value, + source: null, + stack: stack != null ? stack : null, + digest: digest != null ? digest : null + }; } - var _inst = create(); - - refObject.current = _inst; - return function () { - refObject.current = null; - }; - } -} + var ReactFiberErrorDialogWWW = require("ReactFiberErrorDialog"); -function mountImperativeHandle(ref, create, deps) { - { - if (typeof create !== "function") { - error( - "Expected useImperativeHandle() second argument to be a function " + - "that creates a handle. Instead received: %s.", - create !== null ? typeof create : "null" + if (typeof ReactFiberErrorDialogWWW.showErrorDialog !== "function") { + throw new Error( + "Expected ReactFiberErrorDialog.showErrorDialog to be a function." ); } - } // TODO: If deps are provided, should we skip comparing the ref itself? - - var effectDeps = - deps !== null && deps !== undefined ? deps.concat([ref]) : null; - var fiberFlags = Update | LayoutStatic; - - if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { - fiberFlags |= MountLayoutDev; - } - mountEffectImpl( - fiberFlags, - Layout, - imperativeHandleEffect.bind(null, create, ref), - effectDeps - ); -} - -function updateImperativeHandle(ref, create, deps) { - { - if (typeof create !== "function") { - error( - "Expected useImperativeHandle() second argument to be a function " + - "that creates a handle. Instead received: %s.", - create !== null ? typeof create : "null" - ); + function showErrorDialog(boundary, errorInfo) { + var capturedError = { + componentStack: errorInfo.stack !== null ? errorInfo.stack : "", + error: errorInfo.value, + errorBoundary: + boundary !== null && boundary.tag === ClassComponent + ? boundary.stateNode + : null + }; + return ReactFiberErrorDialogWWW.showErrorDialog(capturedError); } - } // TODO: If deps are provided, should we skip comparing the ref itself? - var effectDeps = - deps !== null && deps !== undefined ? deps.concat([ref]) : null; - updateEffectImpl( - Update, - Layout, - imperativeHandleEffect.bind(null, create, ref), - effectDeps - ); -} + function logCapturedError(boundary, errorInfo) { + try { + var logError = showErrorDialog(boundary, errorInfo); // Allow injected showErrorDialog() to prevent default console.error logging. + // This enables renderers like ReactNative to better manage redbox behavior. -function mountDebugValue(value, formatterFn) { - // This hook is normally a no-op. - // The react-debug-hooks package injects its own implementation - // so that e.g. DevTools can display custom hook values. -} + if (logError === false) { + return; + } -var updateDebugValue = mountDebugValue; + var error = errorInfo.value; -function mountCallback(callback, deps) { - var hook = mountWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - hook.memoizedState = [callback, nextDeps]; - return callback; -} + if (true) { + var source = errorInfo.source; + var stack = errorInfo.stack; + var componentStack = stack !== null ? stack : ""; // Browsers support silencing uncaught errors by calling + // `preventDefault()` in window `error` handler. + // We record this information as an expando on the error. -function updateCallback(callback, deps) { - var hook = updateWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var prevState = hook.memoizedState; + if (error != null && error._suppressLogging) { + if (boundary.tag === ClassComponent) { + // The error is recoverable and was silenced. + // Ignore it and don't print the stack addendum. + // This is handy for testing error boundaries without noise. + return; + } // The error is fatal. Since the silencing might have + // been accidental, we'll surface it anyway. + // However, the browser would have silenced the original error + // so we'll print it first, and then print the stack addendum. + + console["error"](error); // Don't transform to our wrapper + // For a more detailed description of this block, see: + // https://github.com/facebook/react/pull/13384 + } - if (nextDeps !== null) { - var prevDeps = prevState[1]; + var componentName = source ? getComponentNameFromFiber(source) : null; + var componentNameMessage = componentName + ? "The above error occurred in the <" + + componentName + + "> component:" + : "The above error occurred in one of your React components:"; + var errorBoundaryMessage; + + if (boundary.tag === HostRoot) { + 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."; + } else { + var errorBoundaryName = + getComponentNameFromFiber(boundary) || "Anonymous"; + errorBoundaryMessage = + "React will try to recreate this component tree from scratch " + + ("using the error boundary you provided, " + + errorBoundaryName + + "."); + } - if (areHookInputsEqual(nextDeps, prevDeps)) { - return prevState[0]; + var combinedMessage = + componentNameMessage + + "\n" + + componentStack + + "\n\n" + + ("" + errorBoundaryMessage); // In development, we provide our own message with just the component stack. + // We don't include the original error message and JS stack because the browser + // has already printed it. Even if the application swallows the error, it is still + // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils. + + console["error"](combinedMessage); // Don't transform to our wrapper + } + } catch (e) { + // This method must not throw, or React internal state will get messed up. + // If console.error is overridden, or logCapturedError() shows a dialog that throws, + // we want to report this error outside of the normal stack as a last resort. + // https://github.com/facebook/react/issues/13188 + setTimeout(function () { + throw e; + }); + } } - } - hook.memoizedState = [callback, nextDeps]; - return callback; -} + function createRootErrorUpdate(fiber, errorInfo, lane) { + var update = createUpdate(lane); // Unmount the root by rendering null. -function mountMemo(nextCreate, deps) { - var hook = mountWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; + update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property + // being called "element". - if (shouldDoubleInvokeUserFnsInHooksDEV) { - nextCreate(); - } + update.payload = { + element: null + }; + var error = errorInfo.value; - var nextValue = nextCreate(); - hook.memoizedState = [nextValue, nextDeps]; - return nextValue; -} + update.callback = function () { + onUncaughtError(error); + logCapturedError(fiber, errorInfo); + }; -function updateMemo(nextCreate, deps) { - var hook = updateWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var prevState = hook.memoizedState; // Assume these are defined. If they're not, areHookInputsEqual will warn. + return update; + } - if (nextDeps !== null) { - var prevDeps = prevState[1]; + function createClassErrorUpdate(fiber, errorInfo, lane) { + var update = createUpdate(lane); + update.tag = CaptureUpdate; + var getDerivedStateFromError = fiber.type.getDerivedStateFromError; - if (areHookInputsEqual(nextDeps, prevDeps)) { - return prevState[0]; - } - } + if (typeof getDerivedStateFromError === "function") { + var error$1 = errorInfo.value; - if (shouldDoubleInvokeUserFnsInHooksDEV) { - nextCreate(); - } + update.payload = function () { + return getDerivedStateFromError(error$1); + }; - var nextValue = nextCreate(); - hook.memoizedState = [nextValue, nextDeps]; - return nextValue; -} + update.callback = function () { + { + markFailedErrorBoundaryForHotReloading(fiber); + } -function mountDeferredValue(value, initialValue) { - var hook = mountWorkInProgressHook(); - return mountDeferredValueImpl(hook, value, initialValue); -} + logCapturedError(fiber, errorInfo); + }; + } -function updateDeferredValue(value, initialValue) { - var hook = updateWorkInProgressHook(); - var resolvedCurrentHook = currentHook; - var prevValue = resolvedCurrentHook.memoizedState; - return updateDeferredValueImpl(hook, prevValue, value, initialValue); -} + var inst = fiber.stateNode; -function rerenderDeferredValue(value, initialValue) { - var hook = updateWorkInProgressHook(); - - if (currentHook === null) { - // This is a rerender during a mount. - return mountDeferredValueImpl(hook, value, initialValue); - } else { - // This is a rerender during an update. - var prevValue = currentHook.memoizedState; - return updateDeferredValueImpl(hook, prevValue, value, initialValue); - } -} + if (inst !== null && typeof inst.componentDidCatch === "function") { + // $FlowFixMe[missing-this-annot] + update.callback = function callback() { + { + markFailedErrorBoundaryForHotReloading(fiber); + } -function mountDeferredValueImpl(hook, value, initialValue) { - if ( - enableUseDeferredValueInitialArg && // When `initialValue` is provided, we defer the initial render even if the - // current render is not synchronous. - initialValue !== undefined && // However, to avoid waterfalls, we do not defer if this render - // was itself spawned by an earlier useDeferredValue. Check if DeferredLane - // is part of the render lanes. - !includesSomeLane(renderLanes, DeferredLane) - ) { - // Render with the initial value - hook.memoizedState = initialValue; // Schedule a deferred render to switch to the final value. - - var deferredLane = requestDeferredLane(); - currentlyRenderingFiber$1.lanes = mergeLanes( - currentlyRenderingFiber$1.lanes, - deferredLane - ); - markSkippedUpdateLanes(deferredLane); - return initialValue; - } else { - hook.memoizedState = value; - return value; - } -} + logCapturedError(fiber, errorInfo); -function updateDeferredValueImpl(hook, prevValue, value, initialValue) { - if (objectIs(value, prevValue)) { - // The incoming value is referentially identical to the currently rendered - // value, so we can bail out quickly. - return value; - } else { - // Received a new value that's different from the current value. - // Check if we're inside a hidden tree - if (isCurrentTreeHidden()) { - // Revealing a prerendered tree is considered the same as mounting new - // one, so we reuse the "mount" path in this case. - var resultValue = mountDeferredValueImpl(hook, value, initialValue); // Unlike during an actual mount, we need to mark this as an update if - // the value changed. - - if (!objectIs(resultValue, prevValue)) { - markWorkInProgressReceivedUpdate(); + if (typeof getDerivedStateFromError !== "function") { + // To preserve the preexisting retry behavior of error boundaries, + // we keep track of which ones already failed during this batch. + // This gets reset before we yield back to the browser. + // TODO: Warn in strict mode if getDerivedStateFromError is + // not defined. + markLegacyErrorBoundaryAsFailed(this); + } + + var error$1 = errorInfo.value; + var stack = errorInfo.stack; + this.componentDidCatch(error$1, { + componentStack: stack !== null ? stack : "" + }); + + { + if (typeof getDerivedStateFromError !== "function") { + // If componentDidCatch is the only error boundary method defined, + // then it needs to call setState to recover from errors. + // If no state update is scheduled then the boundary will swallow the error. + if (!includesSomeLane(fiber.lanes, SyncLane)) { + 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" + ); + } + } + } + }; } - return resultValue; + return update; } - var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes); - - if (shouldDeferValue) { - // This is an urgent update. Since the value has changed, keep using the - // previous value and spawn a deferred render to update it later. - // Schedule a deferred render - var deferredLane = requestDeferredLane(); - currentlyRenderingFiber$1.lanes = mergeLanes( - currentlyRenderingFiber$1.lanes, - deferredLane - ); - markSkippedUpdateLanes(deferredLane); // Reuse the previous value. We do not need to mark this as an update, - // because we did not render a new value. + function resetSuspendedComponent(sourceFiber, rootRenderLanes) { + if (enableLazyContextPropagation) { + var currentSourceFiber = sourceFiber.alternate; - return prevValue; - } else { - // This is not an urgent update, so we can use the latest value regardless - // of what it is. No need to defer it. - // Mark this as an update to prevent the fiber from bailing out. - markWorkInProgressReceivedUpdate(); - hook.memoizedState = value; - return value; - } - } -} + if (currentSourceFiber !== null) { + // Since we never visited the children of the suspended component, we + // need to propagate the context change now, to ensure that we visit + // them during the retry. + // + // We don't have to do this for errors because we retry errors without + // committing in between. So this is specific to Suspense. + propagateParentContextChangesToDeferredTree( + currentSourceFiber, + sourceFiber, + rootRenderLanes + ); + } + } // Reset the memoizedState to what it was before we attempted to render it. + // A legacy mode Suspense quirk, only relevant to hook components. -function startTransition( - fiber, - queue, - pendingState, - finishedState, - callback, - options -) { - var previousPriority = getCurrentUpdatePriority(); - setCurrentUpdatePriority( - higherEventPriority(previousPriority, ContinuousEventPriority) - ); - var prevTransition = ReactCurrentBatchConfig$2.transition; - var currentTransition = {}; - - if (enableAsyncActions) { - // We don't really need to use an optimistic update here, because we - // schedule a second "revert" update below (which we use to suspend the - // transition until the async action scope has finished). But we'll use an - // optimistic update anyway to make it less likely the behavior accidentally - // diverges; for example, both an optimistic update and this one should - // share the same lane. - ReactCurrentBatchConfig$2.transition = currentTransition; - dispatchOptimisticSetState(fiber, false, queue, pendingState); - } else { - ReactCurrentBatchConfig$2.transition = null; - dispatchSetState(fiber, queue, pendingState); - ReactCurrentBatchConfig$2.transition = currentTransition; - } - - if (enableTransitionTracing) { - if (options !== undefined && options.name !== undefined) { - ReactCurrentBatchConfig$2.transition.name = options.name; - ReactCurrentBatchConfig$2.transition.startTime = now$1(); - } - } - - { - ReactCurrentBatchConfig$2.transition._updatedFibers = new Set(); - } - - try { - if (enableAsyncActions) { - var returnValue = callback(); // Check if we're inside an async action scope. If so, we'll entangle - // this new action with the existing scope. - // - // If we're not already inside an async action scope, and this action is - // async, then we'll create a new async scope. - // - // In the async case, the resulting render will suspend until the async - // action scope has finished. + var tag = sourceFiber.tag; if ( - returnValue !== null && - typeof returnValue === "object" && - typeof returnValue.then === "function" + (sourceFiber.mode & ConcurrentMode) === NoMode && + (tag === FunctionComponent || + tag === ForwardRef || + tag === SimpleMemoComponent) ) { - var thenable = returnValue; // This is a thenable that resolves to `finishedState` once the async - // action scope has finished. - - var entangledResult = requestAsyncActionContext( - thenable, - finishedState - ); - dispatchSetState(fiber, queue, entangledResult); - } else { - // This is either `finishedState` or a thenable that resolves to - // `finishedState`, depending on whether we're inside an async - // action scope. - var _entangledResult2 = requestSyncActionContext( - returnValue, - finishedState - ); - - dispatchSetState(fiber, queue, _entangledResult2); - } - } else { - // Async actions are not enabled. - dispatchSetState(fiber, queue, finishedState); - callback(); - } - } catch (error) { - if (enableAsyncActions) { - // This is a trick to get the `useTransition` hook to rethrow the error. - // When it unwraps the thenable with the `use` algorithm, the error - // will be thrown. - var rejectedThenable = { - then: function () {}, - status: "rejected", - reason: error - }; - dispatchSetState(fiber, queue, rejectedThenable); - } else { - // The error rethrowing behavior is only enabled when the async actions - // feature is on, even for sync actions. - throw error; - } - } finally { - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig$2.transition = prevTransition; - - { - if (prevTransition === null && currentTransition._updatedFibers) { - var updatedFibersCount = currentTransition._updatedFibers.size; + var currentSource = sourceFiber.alternate; - currentTransition._updatedFibers.clear(); - - if (updatedFibersCount > 10) { - 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." - ); + if (currentSource) { + sourceFiber.updateQueue = currentSource.updateQueue; + sourceFiber.memoizedState = currentSource.memoizedState; + sourceFiber.lanes = currentSource.lanes; + } else { + sourceFiber.updateQueue = null; + sourceFiber.memoizedState = null; } } - } - } -} - -function mountTransition() { - var stateHook = mountStateImpl(false); // The `start` method never changes. - - var start = startTransition.bind( - null, - currentlyRenderingFiber$1, - stateHook.queue, - true, - false - ); - var hook = mountWorkInProgressHook(); - hook.memoizedState = start; - return [false, start]; -} + } -function updateTransition() { - var _updateState = updateState(), - booleanOrThenable = _updateState[0]; - - var hook = updateWorkInProgressHook(); - var start = hook.memoizedState; - var isPending = - typeof booleanOrThenable === "boolean" - ? booleanOrThenable // This will suspend until the async action scope has finished. - : useThenable(booleanOrThenable); - return [isPending, start]; -} + function markSuspenseBoundaryShouldCapture( + suspenseBoundary, + returnFiber, + sourceFiber, + root, + rootRenderLanes + ) { + // This marks a Suspense boundary so that when we're unwinding the stack, + // it captures the suspended "exception" and does a second (fallback) pass. + if ((suspenseBoundary.mode & ConcurrentMode) === NoMode) { + // Legacy Mode Suspense + // + // If the boundary is in legacy mode, we should *not* + // suspend the commit. Pretend as if the suspended component rendered + // null and keep rendering. When the Suspense boundary completes, + // we'll do a second pass to render the fallback. + if (suspenseBoundary === returnFiber) { + // Special case where we suspended while reconciling the children of + // a Suspense boundary's inner Offscreen wrapper fiber. This happens + // when a React.lazy component is a direct child of a + // Suspense boundary. + // + // Suspense boundaries are implemented as multiple fibers, but they + // are a single conceptual unit. The legacy mode behavior where we + // pretend the suspended fiber committed as `null` won't work, + // because in this case the "suspended" fiber is the inner + // Offscreen wrapper. + // + // Because the contents of the boundary haven't started rendering + // yet (i.e. nothing in the tree has partially rendered) we can + // switch to the regular, concurrent mode behavior: mark the + // boundary with ShouldCapture and enter the unwind phase. + suspenseBoundary.flags |= ShouldCapture; + } else { + suspenseBoundary.flags |= DidCapture; + sourceFiber.flags |= ForceUpdateForLegacySuspense; // We're going to commit this fiber even though it didn't complete. + // But we shouldn't call any lifecycle methods or callbacks. Remove + // all lifecycle effect tags. -function rerenderTransition() { - var _rerenderState = rerenderState(), - booleanOrThenable = _rerenderState[0]; - - var hook = updateWorkInProgressHook(); - var start = hook.memoizedState; - var isPending = - typeof booleanOrThenable === "boolean" - ? booleanOrThenable // This will suspend until the async action scope has finished. - : useThenable(booleanOrThenable); - return [isPending, start]; -} + sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete); -function mountId() { - var hook = mountWorkInProgressHook(); - var root = getWorkInProgressRoot(); // TODO: In Fizz, id generation is specific to each server config. Maybe we - // should do this in Fiber, too? Deferring this decision for now because - // there's no other place to store the prefix except for an internal field on - // the public createRoot object, which the fiber tree does not currently have - // a reference to. - - var identifierPrefix = root.identifierPrefix; - var id; - - { - // Use a lowercase r prefix for client-generated ids. - var globalClientId = globalClientIdCounter++; - id = ":" + identifierPrefix + "r" + globalClientId.toString(32) + ":"; - } - - hook.memoizedState = id; - return id; -} + if (sourceFiber.tag === ClassComponent) { + var currentSourceFiber = sourceFiber.alternate; -function updateId() { - var hook = updateWorkInProgressHook(); - var id = hook.memoizedState; - return id; -} + if (currentSourceFiber === null) { + // This is a new mount. Change the tag so it's not mistaken for a + // completed class component. For example, we should not call + // componentWillUnmount if it is deleted. + sourceFiber.tag = IncompleteClassComponent; + } else { + // When we try rendering again, we should not reuse the current fiber, + // since it's known to be in an inconsistent state. Use a force update to + // prevent a bail out. + var update = createUpdate(SyncLane); + update.tag = ForceUpdate; + enqueueUpdate(sourceFiber, update, SyncLane); + } + } // The source fiber did not complete. Mark it with Sync priority to + // indicate that it still has pending work. -function mountRefresh() { - var hook = mountWorkInProgressHook(); - var refresh = (hook.memoizedState = refreshCache.bind( - null, - currentlyRenderingFiber$1 - )); - return refresh; -} + sourceFiber.lanes = mergeLanes(sourceFiber.lanes, SyncLane); + } -function updateRefresh() { - var hook = updateWorkInProgressHook(); - return hook.memoizedState; -} + return suspenseBoundary; + } // Confirmed that the boundary is in a concurrent mode tree. Continue + // with the normal suspend path. + // + // After this we'll use a set of heuristics to determine whether this + // render pass will run to completion or restart or "suspend" the commit. + // The actual logic for this is spread out in different places. + // + // This first principle is that if we're going to suspend when we complete + // a root, then we should also restart if we get an update or ping that + // might unsuspend it, and vice versa. The only reason to suspend is + // because you think you might want to restart before committing. However, + // it doesn't make sense to restart only while in the period we're suspended. + // + // Restarting too aggressively is also not good because it starves out any + // intermediate loading state. So we use heuristics to determine when. + // Suspense Heuristics + // + // If nothing threw a Promise or all the same fallbacks are already showing, + // then don't suspend/restart. + // + // If this is an initial render of a new tree of Suspense boundaries and + // those trigger a fallback, then don't suspend/restart. We want to ensure + // that we can show the initial loading state as quickly as possible. + // + // If we hit a "Delayed" case, such as when we'd switch from content back into + // a fallback, then we should always suspend/restart. Transitions apply + // to this case. If none is defined, JND is used instead. + // + // If we're already showing a fallback and it gets "retried", allowing us to show + // another level, but there's still an inner boundary that would show a fallback, + // then we suspend/restart for 500ms since the last time we showed a fallback + // anywhere in the tree. This effectively throttles progressive loading into a + // consistent train of commits. This also gives us an opportunity to restart to + // get to the completed state slightly earlier. + // + // If there's ambiguity due to batching it's resolved in preference of: + // 1) "delayed", 2) "initial render", 3) "retry". + // + // We want to ensure that a "busy" state doesn't get force committed. We want to + // ensure that new initial loading states can commit as soon as possible. -function refreshCache(fiber, seedKey, seedValue) { - // TODO: Consider warning if the refresh is at discrete priority, or if we - // otherwise suspect that it wasn't batched properly. + suspenseBoundary.flags |= ShouldCapture; // TODO: I think we can remove this, since we now use `DidCapture` in + // the begin phase to prevent an early bailout. - var provider = fiber.return; + suspenseBoundary.lanes = rootRenderLanes; + return suspenseBoundary; + } - while (provider !== null) { - switch (provider.tag) { - case CacheComponent: - case HostRoot: { - // Schedule an update on the cache boundary to trigger a refresh. - var lane = requestUpdateLane(provider); - var refreshUpdate = createUpdate(lane); - var root = enqueueUpdate(provider, refreshUpdate, lane); + function throwException( + root, + returnFiber, + sourceFiber, + value, + rootRenderLanes + ) { + // The source fiber did not complete. + sourceFiber.flags |= Incomplete; - if (root !== null) { - scheduleUpdateOnFiber(root, provider, lane); - entangleTransitions(root, provider, lane); - } // TODO: If a refresh never commits, the new cache created here must be - // released. A simple case is start refreshing a cache boundary, but then - // unmount that boundary before the refresh completes. + { + if (isDevToolsPresent) { + // If we have pending work still, restore the original updaters + restorePendingUpdaters(root, rootRenderLanes); + } + } - var seededCache = createCache(); + if (value !== null && typeof value === "object") { + if (typeof value.then === "function") { + // This is a wakeable. The component suspended. + var wakeable = value; + resetSuspendedComponent(sourceFiber, rootRenderLanes); - if (seedKey !== null && seedKey !== undefined && root !== null) { { - // Seed the cache with the value passed by the caller. This could be - // from a server mutation, or it could be a streaming response. - seededCache.data.set(seedKey, seedValue); - } - } + if (enableDebugTracing) { + if (sourceFiber.mode & DebugTracingMode) { + var name = getComponentNameFromFiber(sourceFiber) || "Unknown"; + logComponentSuspended(name, wakeable); + } + } + } // Mark the nearest Suspense boundary to switch to rendering a fallback. + + var suspenseBoundary = getSuspenseHandler(); + + if (suspenseBoundary !== null) { + switch (suspenseBoundary.tag) { + case SuspenseComponent: { + // If this suspense boundary is not already showing a fallback, mark + // the in-progress render as suspended. We try to perform this logic + // as soon as soon as possible during the render phase, so the work + // loop can know things like whether it's OK to switch to other tasks, + // or whether it can wait for data to resolve before continuing. + // TODO: Most of these checks are already performed when entering a + // Suspense boundary. We should track the information on the stack so + // we don't have to recompute it on demand. This would also allow us + // to unify with `use` which needs to perform this logic even sooner, + // before `throwException` is called. + if (sourceFiber.mode & ConcurrentMode) { + if (getShellBoundary() === null) { + // Suspended in the "shell" of the app. This is an undesirable + // loading state. We should avoid committing this tree. + renderDidSuspendDelayIfPossible(); + } else { + // If we suspended deeper than the shell, we don't need to delay + // the commmit. However, we still call renderDidSuspend if this is + // a new boundary, to tell the work loop that a new fallback has + // appeared during this render. + // TODO: Theoretically we should be able to delete this branch. + // It's currently used for two things: 1) to throttle the + // appearance of successive loading states, and 2) in + // SuspenseList, to determine whether the children include any + // pending fallbacks. For 1, we should apply throttling to all + // retries, not just ones that render an additional fallback. For + // 2, we should check subtreeFlags instead. Then we can delete + // this branch. + var current = suspenseBoundary.alternate; + + if (current === null) { + renderDidSuspend(); + } + } + } - var payload = { - cache: seededCache - }; - refreshUpdate.payload = payload; - return; - } - } + suspenseBoundary.flags &= ~ForceClientRender; + markSuspenseBoundaryShouldCapture( + suspenseBoundary, + returnFiber, + sourceFiber, + root, + rootRenderLanes + ); // Retry listener + // + // If the fallback does commit, we need to attach a different type of + // listener. This one schedules an update on the Suspense boundary to + // turn the fallback state off. + // + // Stash the wakeable on the boundary fiber so we can access it in the + // commit phase. + // + // When the wakeable resolves, we'll attempt to render the boundary + // again ("retry"). + // Check if this is a Suspensey resource. We do not attach retry + // listeners to these, because we don't actually need them for + // rendering. Only for committing. Instead, if a fallback commits + // and the only thing that suspended was a Suspensey resource, we + // retry immediately. + // TODO: Refactor throwException so that we don't have to do this type + // check. The caller already knows what the cause was. + + var isSuspenseyResource = + wakeable === noopSuspenseyCommitThenable; + + if (isSuspenseyResource) { + suspenseBoundary.flags |= ScheduleRetry; + } else { + var retryQueue = suspenseBoundary.updateQueue; - provider = provider.return; - } // TODO: Warn if unmounted? -} + if (retryQueue === null) { + suspenseBoundary.updateQueue = new Set([wakeable]); + } else { + retryQueue.add(wakeable); + } // We only attach ping listeners in concurrent mode. Legacy + // Suspense always commits fallbacks synchronously, so there are + // no pings. -function dispatchReducerAction(fiber, queue, action) { - { - if (typeof arguments[3] === "function") { - 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()." - ); - } - } + if (suspenseBoundary.mode & ConcurrentMode) { + attachPingListener(root, wakeable, rootRenderLanes); + } + } - var lane = requestUpdateLane(fiber); - var update = { - lane: lane, - revertLane: NoLane, - action: action, - hasEagerState: false, - eagerState: null, - next: null - }; + return; + } - if (isRenderPhaseUpdate(fiber)) { - enqueueRenderPhaseUpdate(queue, update); - } else { - var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); + case OffscreenComponent: { + if (suspenseBoundary.mode & ConcurrentMode) { + suspenseBoundary.flags |= ShouldCapture; - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane); - entangleTransitionUpdate(root, queue, lane); - } - } + var _isSuspenseyResource = + wakeable === noopSuspenseyCommitThenable; - markUpdateInDevTools(fiber, lane, action); -} + if (_isSuspenseyResource) { + suspenseBoundary.flags |= ScheduleRetry; + } else { + var offscreenQueue = suspenseBoundary.updateQueue; + + if (offscreenQueue === null) { + var newOffscreenQueue = { + transitions: null, + markerInstances: null, + retryQueue: new Set([wakeable]) + }; + suspenseBoundary.updateQueue = newOffscreenQueue; + } else { + var _retryQueue = offscreenQueue.retryQueue; -function dispatchSetState(fiber, queue, action) { - { - if (typeof arguments[3] === "function") { - 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()." - ); - } - } + if (_retryQueue === null) { + offscreenQueue.retryQueue = new Set([wakeable]); + } else { + _retryQueue.add(wakeable); + } + } - var lane = requestUpdateLane(fiber); - var update = { - lane: lane, - revertLane: NoLane, - action: action, - hasEagerState: false, - eagerState: null, - next: null - }; + attachPingListener(root, wakeable, rootRenderLanes); + } - if (isRenderPhaseUpdate(fiber)) { - enqueueRenderPhaseUpdate(queue, update); - } else { - var alternate = fiber.alternate; + return; + } + } + } - if ( - fiber.lanes === NoLanes && - (alternate === null || alternate.lanes === NoLanes) - ) { - // The queue is currently empty, which means we can eagerly compute the - // next state before entering the render phase. If the new state is the - // same as the current state, we may be able to bail out entirely. - var lastRenderedReducer = queue.lastRenderedReducer; + throw new Error( + "Unexpected Suspense handler tag (" + + suspenseBoundary.tag + + "). This " + + "is a bug in React." + ); + } else { + // No boundary was found. Unless this is a sync update, this is OK. + // We can suspend and wait for more data to arrive. + if (root.tag === ConcurrentRoot) { + // In a concurrent root, suspending without a Suspense boundary is + // allowed. It will suspend indefinitely without committing. + // + // TODO: Should we have different behavior for discrete updates? What + // about flushSync? Maybe it should put the tree into an inert state, + // and potentially log a warning. Revisit this for a future release. + attachPingListener(root, wakeable, rootRenderLanes); + renderDidSuspendDelayIfPossible(); + return; + } else { + // In a legacy root, suspending without a boundary is always an error. + 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." + ); + value = uncaughtSuspenseError; + } + } + } + } // This is a regular error, not a Suspense wakeable. - if (lastRenderedReducer !== null) { - var prevDispatcher; + value = createCapturedValueAtFiber(value, sourceFiber); + renderDidError(value); // We didn't find a boundary that could handle this type of exception. Start + // over and traverse parent path again, this time treating the exception + // as an error. - { - prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; - } + var workInProgress = returnFiber; - try { - var currentState = queue.lastRenderedState; - var eagerState = lastRenderedReducer(currentState, action); // Stash the eagerly computed state, and the reducer used to compute - // it, on the update object. If the reducer hasn't changed by the - // time we enter the render phase, then the eager state can be used - // without calling the reducer again. - - update.hasEagerState = true; - update.eagerState = eagerState; - - if (objectIs(eagerState, currentState)) { - // Fast path. We can bail out without scheduling React to re-render. - // It's still possible that we'll need to rebase this update later, - // if the component re-renders for a different reason and by that - // time the reducer has changed. - // TODO: Do we still need to entangle transitions in this case? - enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update); + do { + switch (workInProgress.tag) { + case HostRoot: { + var _errorInfo = value; + workInProgress.flags |= ShouldCapture; + var lane = pickArbitraryLane(rootRenderLanes); + workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); + var update = createRootErrorUpdate( + workInProgress, + _errorInfo, + lane + ); + enqueueCapturedUpdate(workInProgress, update); return; } - } catch (error) { - // Suppress the error. It will throw again in the render phase. - } finally { - { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - } - } - } - - var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane); - entangleTransitionUpdate(root, queue, lane); - } - } + case ClassComponent: + // Capture and retry + var errorInfo = value; + var ctor = workInProgress.type; + var instance = workInProgress.stateNode; - markUpdateInDevTools(fiber, lane, action); -} + if ( + (workInProgress.flags & DidCapture) === NoFlags$1 && + (typeof ctor.getDerivedStateFromError === "function" || + (instance !== null && + typeof instance.componentDidCatch === "function" && + !isAlreadyFailedLegacyErrorBoundary(instance))) + ) { + workInProgress.flags |= ShouldCapture; -function dispatchOptimisticSetState(fiber, throwIfDuringRender, queue, action) { - { - if (ReactCurrentBatchConfig$2.transition === null) { - // An optimistic update occurred, but startTransition is not on the stack. - // There are two likely scenarios. - // One possibility is that the optimistic update is triggered by a regular - // event handler (e.g. `onSubmit`) instead of an action. This is a mistake - // and we will warn. - // The other possibility is the optimistic update is inside an async - // action, but after an `await`. In this case, we can make it "just work" - // by associating the optimistic update with the pending async action. - // Technically it's possible that the optimistic update is unrelated to - // the pending action, but we don't have a way of knowing this for sure - // because browsers currently do not provide a way to track async scope. - // (The AsyncContext proposal, if it lands, will solve this in the - // future.) However, this is no different than the problem of unrelated - // transitions being grouped together — it's not wrong per se, but it's - // not ideal. - // Once AsyncContext starts landing in browsers, we will provide better - // warnings in development for these cases. - if (peekEntangledActionLane() !== NoLane); - else { - // There's no pending async action. The most likely cause is that we're - // inside a regular event handler (e.g. onSubmit) instead of an action. - error( - "An optimistic state update occurred outside a transition or " + - "action. To fix, move the update to an action, or wrap " + - "with startTransition." - ); - } - } - } - - var update = { - // An optimistic update commits synchronously. - lane: SyncLane, - // After committing, the optimistic update is "reverted" using the same - // lane as the transition it's associated with. - revertLane: requestTransitionLane(), - action: action, - hasEagerState: false, - eagerState: null, - next: null - }; - - if (isRenderPhaseUpdate(fiber)) { - // When calling startTransition during render, this warns instead of - // throwing because throwing would be a breaking change. setOptimisticState - // is a new API so it's OK to throw. - if (throwIfDuringRender) { - throw new Error("Cannot update optimistic state while rendering."); - } else { - // startTransition was called during render. We don't need to do anything - // besides warn here because the render phase update would be overidden by - // the second update, anyway. We can remove this branch and make it throw - // in a future release. - { - error("Cannot call startTransition while rendering."); - } - } - } else { - var root = enqueueConcurrentHookUpdate(fiber, queue, update, SyncLane); + var _lane = pickArbitraryLane(rootRenderLanes); - if (root !== null) { - // NOTE: The optimistic update implementation assumes that the transition - // will never be attempted before the optimistic update. This currently - // holds because the optimistic update is always synchronous. If we ever - // change that, we'll need to account for this. - scheduleUpdateOnFiber(root, fiber, SyncLane); // Optimistic updates are always synchronous, so we don't need to call - // entangleTransitionUpdate here. - } - } + workInProgress.lanes = mergeLanes(workInProgress.lanes, _lane); // Schedule the error boundary to re-render using updated state - markUpdateInDevTools(fiber, SyncLane, action); -} + var _update = createClassErrorUpdate( + workInProgress, + errorInfo, + _lane + ); -function isRenderPhaseUpdate(fiber) { - var alternate = fiber.alternate; - return ( - fiber === currentlyRenderingFiber$1 || - (alternate !== null && alternate === currentlyRenderingFiber$1) - ); -} + enqueueCapturedUpdate(workInProgress, _update); + return; + } -function enqueueRenderPhaseUpdate(queue, update) { - // This is a render phase update. Stash it in a lazily-created map of - // queue -> linked list of updates. After this render pass, we'll restart - // and apply the stashed updates on top of the work-in-progress hook. - didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = - true; - var pending = queue.pending; - - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; - } - - queue.pending = update; -} // TODO: Move to ReactFiberConcurrentUpdates? - -function entangleTransitionUpdate(root, queue, lane) { - if (isTransitionLane(lane)) { - var queueLanes = queue.lanes; // If any entangled lanes are no longer pending on the root, then they - // must have finished. We can remove them from the shared queue, which - // represents a superset of the actually pending lanes. In some cases we - // may entangle more than we need to, but that's OK. In fact it's worse if - // we *don't* entangle when we should. - - queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. - - var newQueueLanes = mergeLanes(queueLanes, lane); - queue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if - // the lane finished since the last time we entangled it. So we need to - // entangle it again, just to be sure. - - markRootEntangled(root, newQueueLanes); - } -} + break; + } // $FlowFixMe[incompatible-type] we bail out when we get a null -function markUpdateInDevTools(fiber, lane, action) { - { - if (enableDebugTracing) { - if (fiber.mode & DebugTracingMode) { - var name = getComponentNameFromFiber(fiber) || "Unknown"; - logStateUpdateScheduled(name, lane, action); - } + workInProgress = workInProgress.return; + } while (workInProgress !== null); } - } - if (enableSchedulingProfiler) { - markStateUpdateScheduled(fiber, lane); - } -} - -var ContextOnlyDispatcher = { - readContext: readContext, - use: use, - useCallback: throwInvalidHookError, - useContext: throwInvalidHookError, - useEffect: throwInvalidHookError, - useImperativeHandle: throwInvalidHookError, - useInsertionEffect: throwInvalidHookError, - useLayoutEffect: throwInvalidHookError, - useMemo: throwInvalidHookError, - useReducer: throwInvalidHookError, - useRef: throwInvalidHookError, - useState: throwInvalidHookError, - useDebugValue: throwInvalidHookError, - useDeferredValue: throwInvalidHookError, - useTransition: throwInvalidHookError, - useSyncExternalStore: throwInvalidHookError, - useId: throwInvalidHookError -}; - -{ - ContextOnlyDispatcher.useCacheRefresh = throwInvalidHookError; -} + var TransitionRoot = 0; + var TransitionTracingMarker = 1; + function processTransitionCallbacks( + pendingTransitions, + endTime, + callbacks + ) { + if (enableTransitionTracing) { + if (pendingTransitions !== null) { + var transitionStart = pendingTransitions.transitionStart; + var onTransitionStart = callbacks.onTransitionStart; -{ - ContextOnlyDispatcher.useMemoCache = throwInvalidHookError; -} + if (transitionStart !== null && onTransitionStart != null) { + transitionStart.forEach(function (transition) { + return onTransitionStart(transition.name, transition.startTime); + }); + } -{ - ContextOnlyDispatcher.useEffectEvent = throwInvalidHookError; -} + var markerProgress = pendingTransitions.markerProgress; + var onMarkerProgress = callbacks.onMarkerProgress; + + if (onMarkerProgress != null && markerProgress !== null) { + markerProgress.forEach(function (markerInstance, markerName) { + if (markerInstance.transitions !== null) { + // TODO: Clone the suspense object so users can't modify it + var pending = + markerInstance.pendingBoundaries !== null + ? Array.from(markerInstance.pendingBoundaries.values()) + : []; + markerInstance.transitions.forEach(function (transition) { + onMarkerProgress( + transition.name, + markerName, + transition.startTime, + endTime, + pending + ); + }); + } + }); + } -if (enableAsyncActions) { - ContextOnlyDispatcher.useOptimistic = throwInvalidHookError; -} + var markerComplete = pendingTransitions.markerComplete; + var onMarkerComplete = callbacks.onMarkerComplete; -var HooksDispatcherOnMountInDEV = null; -var HooksDispatcherOnMountWithHookTypesInDEV = null; -var HooksDispatcherOnUpdateInDEV = null; -var HooksDispatcherOnRerenderInDEV = null; -var InvalidNestedHooksDispatcherOnMountInDEV = null; -var InvalidNestedHooksDispatcherOnUpdateInDEV = null; -var InvalidNestedHooksDispatcherOnRerenderInDEV = null; - -{ - var warnInvalidContextAccess = function () { - 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()." - ); - }; - - var warnInvalidHookAccess = function () { - 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" - ); - }; - - HooksDispatcherOnMountInDEV = { - readContext: function (context) { - return readContext(context); - }, - use: use, - useCallback: function (callback, deps) { - currentHookNameInDev = "useCallback"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - return mountCallback(callback, deps); - }, - useContext: function (context) { - currentHookNameInDev = "useContext"; - mountHookTypesDev(); - return readContext(context); - }, - useEffect: function (create, deps) { - currentHookNameInDev = "useEffect"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - return mountEffect(create, deps); - }, - useImperativeHandle: function (ref, create, deps) { - currentHookNameInDev = "useImperativeHandle"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - return mountImperativeHandle(ref, create, deps); - }, - useInsertionEffect: function (create, deps) { - currentHookNameInDev = "useInsertionEffect"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - return mountInsertionEffect(create, deps); - }, - useLayoutEffect: function (create, deps) { - currentHookNameInDev = "useLayoutEffect"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - return mountLayoutEffect(create, deps); - }, - useMemo: function (create, deps) { - currentHookNameInDev = "useMemo"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + if (markerComplete !== null && onMarkerComplete != null) { + markerComplete.forEach(function (transitions, markerName) { + transitions.forEach(function (transition) { + onMarkerComplete( + transition.name, + markerName, + transition.startTime, + endTime + ); + }); + }); + } - try { - return mountMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useReducer: function (reducer, initialArg, init) { - currentHookNameInDev = "useReducer"; - mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + var markerIncomplete = pendingTransitions.markerIncomplete; + var onMarkerIncomplete = callbacks.onMarkerIncomplete; + + if (onMarkerIncomplete != null && markerIncomplete !== null) { + markerIncomplete.forEach(function (_ref, markerName) { + var transitions = _ref.transitions, + aborts = _ref.aborts; + transitions.forEach(function (transition) { + var filteredAborts = []; + aborts.forEach(function (abort) { + switch (abort.reason) { + case "marker": { + filteredAborts.push({ + type: "marker", + name: abort.name, + endTime: endTime + }); + break; + } - try { - return mountReducer(reducer, initialArg, init); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useRef: function (initialValue) { - currentHookNameInDev = "useRef"; - mountHookTypesDev(); - return mountRef(initialValue); - }, - useState: function (initialState) { - currentHookNameInDev = "useState"; - mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + case "suspense": { + filteredAborts.push({ + type: "suspense", + name: abort.name, + endTime: endTime + }); + break; + } + } + }); - try { - return mountState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function (value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - mountHookTypesDev(); - return mountDebugValue(); - }, - useDeferredValue: function (value, initialValue) { - currentHookNameInDev = "useDeferredValue"; - mountHookTypesDev(); - return mountDeferredValue(value, initialValue); - }, - useTransition: function () { - currentHookNameInDev = "useTransition"; - mountHookTypesDev(); - return mountTransition(); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - mountHookTypesDev(); - return mountSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - mountHookTypesDev(); - return mountId(); - } - }; - - { - HooksDispatcherOnMountInDEV.useCacheRefresh = function useCacheRefresh() { - currentHookNameInDev = "useCacheRefresh"; - mountHookTypesDev(); - return mountRefresh(); - }; - } + if (filteredAborts.length > 0) { + onMarkerIncomplete( + transition.name, + markerName, + transition.startTime, + filteredAborts + ); + } + }); + }); + } - { - HooksDispatcherOnMountInDEV.useMemoCache = useMemoCache; - } + var transitionProgress = pendingTransitions.transitionProgress; + var onTransitionProgress = callbacks.onTransitionProgress; - { - HooksDispatcherOnMountInDEV.useEffectEvent = function useEffectEvent( - callback - ) { - currentHookNameInDev = "useEffectEvent"; - mountHookTypesDev(); - return mountEvent(callback); - }; - } + if (onTransitionProgress != null && transitionProgress !== null) { + transitionProgress.forEach(function (pending, transition) { + onTransitionProgress( + transition.name, + transition.startTime, + endTime, + Array.from(pending.values()) + ); + }); + } - if (enableAsyncActions) { - HooksDispatcherOnMountInDEV.useOptimistic = function useOptimistic( - passthrough, - reducer - ) { - currentHookNameInDev = "useOptimistic"; - mountHookTypesDev(); - return mountOptimistic(passthrough); - }; - } - - HooksDispatcherOnMountWithHookTypesInDEV = { - readContext: function (context) { - return readContext(context); - }, - use: use, - useCallback: function (callback, deps) { - currentHookNameInDev = "useCallback"; - updateHookTypesDev(); - return mountCallback(callback, deps); - }, - useContext: function (context) { - currentHookNameInDev = "useContext"; - updateHookTypesDev(); - return readContext(context); - }, - useEffect: function (create, deps) { - currentHookNameInDev = "useEffect"; - updateHookTypesDev(); - return mountEffect(create, deps); - }, - useImperativeHandle: function (ref, create, deps) { - currentHookNameInDev = "useImperativeHandle"; - updateHookTypesDev(); - return mountImperativeHandle(ref, create, deps); - }, - useInsertionEffect: function (create, deps) { - currentHookNameInDev = "useInsertionEffect"; - updateHookTypesDev(); - return mountInsertionEffect(create, deps); - }, - useLayoutEffect: function (create, deps) { - currentHookNameInDev = "useLayoutEffect"; - updateHookTypesDev(); - return mountLayoutEffect(create, deps); - }, - useMemo: function (create, deps) { - currentHookNameInDev = "useMemo"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + var transitionComplete = pendingTransitions.transitionComplete; + var onTransitionComplete = callbacks.onTransitionComplete; - try { - return mountMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + if (transitionComplete !== null && onTransitionComplete != null) { + transitionComplete.forEach(function (transition) { + return onTransitionComplete( + transition.name, + transition.startTime, + endTime + ); + }); + } + } } - }, - useReducer: function (reducer, initialArg, init) { - currentHookNameInDev = "useReducer"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + } // For every tracing marker, store a pointer to it. We will later access it + // to get the set of suspense boundaries that need to resolve before the + // tracing marker can be logged as complete + // This code lives separate from the ReactFiberTransition code because + // we push and pop on the tracing marker, not the suspense boundary - try { - return mountReducer(reducer, initialArg, init); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useRef: function (initialValue) { - currentHookNameInDev = "useRef"; - updateHookTypesDev(); - return mountRef(initialValue); - }, - useState: function (initialState) { - currentHookNameInDev = "useState"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + var markerInstanceStack = createCursor(null); + function pushRootMarkerInstance(workInProgress) { + if (enableTransitionTracing) { + // On the root, every transition gets mapped to it's own map of + // suspense boundaries. The transition is marked as complete when + // the suspense boundaries map is empty. We do this because every + // transition completes at different times and depends on different + // suspense boundaries to complete. We store all the transitions + // along with its map of suspense boundaries in the root incomplete + // transitions map. Each entry in this map functions like a tracing + // marker does, so we can push it onto the marker instance stack + var transitions = getWorkInProgressTransitions(); + var root = workInProgress.stateNode; - try { - return mountState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function (value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - updateHookTypesDev(); - return mountDebugValue(); - }, - useDeferredValue: function (value, initialValue) { - currentHookNameInDev = "useDeferredValue"; - updateHookTypesDev(); - return mountDeferredValue(value, initialValue); - }, - useTransition: function () { - currentHookNameInDev = "useTransition"; - updateHookTypesDev(); - return mountTransition(); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - updateHookTypesDev(); - return mountSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - updateHookTypesDev(); - return mountId(); - } - }; - - { - HooksDispatcherOnMountWithHookTypesInDEV.useCacheRefresh = - function useCacheRefresh() { - currentHookNameInDev = "useCacheRefresh"; - updateHookTypesDev(); - return mountRefresh(); - }; - } - - { - HooksDispatcherOnMountWithHookTypesInDEV.useMemoCache = useMemoCache; - } - - { - HooksDispatcherOnMountWithHookTypesInDEV.useEffectEvent = - function useEffectEvent(callback) { - currentHookNameInDev = "useEffectEvent"; - updateHookTypesDev(); - return mountEvent(callback); - }; - } - - if (enableAsyncActions) { - HooksDispatcherOnMountWithHookTypesInDEV.useOptimistic = - function useOptimistic(passthrough, reducer) { - currentHookNameInDev = "useOptimistic"; - updateHookTypesDev(); - return mountOptimistic(passthrough); - }; - } - - HooksDispatcherOnUpdateInDEV = { - readContext: function (context) { - return readContext(context); - }, - use: use, - useCallback: function (callback, deps) { - currentHookNameInDev = "useCallback"; - updateHookTypesDev(); - return updateCallback(callback, deps); - }, - useContext: function (context) { - currentHookNameInDev = "useContext"; - updateHookTypesDev(); - return readContext(context); - }, - useEffect: function (create, deps) { - currentHookNameInDev = "useEffect"; - updateHookTypesDev(); - return updateEffect(create, deps); - }, - useImperativeHandle: function (ref, create, deps) { - currentHookNameInDev = "useImperativeHandle"; - updateHookTypesDev(); - return updateImperativeHandle(ref, create, deps); - }, - useInsertionEffect: function (create, deps) { - currentHookNameInDev = "useInsertionEffect"; - updateHookTypesDev(); - return updateInsertionEffect(create, deps); - }, - useLayoutEffect: function (create, deps) { - currentHookNameInDev = "useLayoutEffect"; - updateHookTypesDev(); - return updateLayoutEffect(create, deps); - }, - useMemo: function (create, deps) { - currentHookNameInDev = "useMemo"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + if (transitions !== null) { + transitions.forEach(function (transition) { + if (!root.incompleteTransitions.has(transition)) { + var markerInstance = { + tag: TransitionRoot, + transitions: new Set([transition]), + pendingBoundaries: null, + aborts: null, + name: null + }; + root.incompleteTransitions.set(transition, markerInstance); + } + }); + } - try { - return updateMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + var markerInstances = []; // For ever transition on the suspense boundary, we push the transition + // along with its map of pending suspense boundaries onto the marker + // instance stack. + + root.incompleteTransitions.forEach(function (markerInstance) { + markerInstances.push(markerInstance); + }); + push(markerInstanceStack, markerInstances, workInProgress); + } + } + function popRootMarkerInstance(workInProgress) { + if (enableTransitionTracing) { + pop(markerInstanceStack, workInProgress); + } + } + function pushMarkerInstance(workInProgress, markerInstance) { + if (enableTransitionTracing) { + if (markerInstanceStack.current === null) { + push(markerInstanceStack, [markerInstance], workInProgress); + } else { + push( + markerInstanceStack, + markerInstanceStack.current.concat(markerInstance), + workInProgress + ); + } + } + } + function popMarkerInstance(workInProgress) { + if (enableTransitionTracing) { + pop(markerInstanceStack, workInProgress); + } + } + function getMarkerInstances() { + if (enableTransitionTracing) { + return markerInstanceStack.current; } - }, - useReducer: function (reducer, initialArg, init) { - currentHookNameInDev = "useReducer"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; - try { - return updateReducer(reducer, initialArg, init); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useRef: function (initialValue) { - currentHookNameInDev = "useRef"; - updateHookTypesDev(); - return updateRef(); - }, - useState: function (initialState) { - currentHookNameInDev = "useState"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + return null; + } - try { - return updateState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function (value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - updateHookTypesDev(); - return updateDebugValue(); - }, - useDeferredValue: function (value, initialValue) { - currentHookNameInDev = "useDeferredValue"; - updateHookTypesDev(); - return updateDeferredValue(value, initialValue); - }, - useTransition: function () { - currentHookNameInDev = "useTransition"; - updateHookTypesDev(); - return updateTransition(); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - updateHookTypesDev(); - return updateId(); - } - }; - - { - HooksDispatcherOnUpdateInDEV.useCacheRefresh = function useCacheRefresh() { - currentHookNameInDev = "useCacheRefresh"; - updateHookTypesDev(); - return updateRefresh(); - }; - } + var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; // A special exception that's used to unwind the stack when an update flows + // into a dehydrated boundary. - { - HooksDispatcherOnUpdateInDEV.useMemoCache = useMemoCache; - } + var SelectiveHydrationException = new Error( + "This is not a real error. It's an implementation detail of React's " + + "selective hydration feature. If this leaks into userspace, it's a bug in " + + "React. Please file an issue." + ); + var didReceiveUpdate = false; + var didWarnAboutBadClass; + var didWarnAboutModulePatternComponent; + var didWarnAboutContextTypeOnFunctionComponent; + var didWarnAboutGetDerivedStateOnFunctionComponent; + var didWarnAboutFunctionRefs; + var didWarnAboutReassigningProps; + var didWarnAboutRevealOrder; + var didWarnAboutTailOptions; + var didWarnAboutDefaultPropsOnFunctionComponent; - { - HooksDispatcherOnUpdateInDEV.useEffectEvent = function useEffectEvent( - callback + { + didWarnAboutBadClass = {}; + didWarnAboutModulePatternComponent = {}; + didWarnAboutContextTypeOnFunctionComponent = {}; + didWarnAboutGetDerivedStateOnFunctionComponent = {}; + didWarnAboutFunctionRefs = {}; + didWarnAboutReassigningProps = false; + didWarnAboutRevealOrder = {}; + didWarnAboutTailOptions = {}; + didWarnAboutDefaultPropsOnFunctionComponent = {}; + } + + function reconcileChildren( + current, + workInProgress, + nextChildren, + renderLanes ) { - currentHookNameInDev = "useEffectEvent"; - updateHookTypesDev(); - return updateEvent(callback); - }; - } + if (current === null) { + // If this is a fresh new component that hasn't been rendered yet, we + // won't update its child set by applying minimal side-effects. Instead, + // we will add them all to the child before it gets rendered. That means + // we can optimize this reconciliation pass by not tracking side-effects. + workInProgress.child = mountChildFibers( + workInProgress, + null, + nextChildren, + renderLanes + ); + } else { + // If the current child is the same as the work in progress, it means that + // we haven't yet started any work on these children. Therefore, we use + // the clone algorithm to create a copy of all the current children. + // If we had any progressed work already, that is invalid at this point so + // let's throw it out. + workInProgress.child = reconcileChildFibers( + workInProgress, + current.child, + nextChildren, + renderLanes + ); + } + } - if (enableAsyncActions) { - HooksDispatcherOnUpdateInDEV.useOptimistic = function useOptimistic( - passthrough, - reducer + function forceUnmountCurrentAndReconcile( + current, + workInProgress, + nextChildren, + renderLanes ) { - currentHookNameInDev = "useOptimistic"; - updateHookTypesDev(); - return updateOptimistic(passthrough, reducer); - }; - } - - HooksDispatcherOnRerenderInDEV = { - readContext: function (context) { - return readContext(context); - }, - use: use, - useCallback: function (callback, deps) { - currentHookNameInDev = "useCallback"; - updateHookTypesDev(); - return updateCallback(callback, deps); - }, - useContext: function (context) { - currentHookNameInDev = "useContext"; - updateHookTypesDev(); - return readContext(context); - }, - useEffect: function (create, deps) { - currentHookNameInDev = "useEffect"; - updateHookTypesDev(); - return updateEffect(create, deps); - }, - useImperativeHandle: function (ref, create, deps) { - currentHookNameInDev = "useImperativeHandle"; - updateHookTypesDev(); - return updateImperativeHandle(ref, create, deps); - }, - useInsertionEffect: function (create, deps) { - currentHookNameInDev = "useInsertionEffect"; - updateHookTypesDev(); - return updateInsertionEffect(create, deps); - }, - useLayoutEffect: function (create, deps) { - currentHookNameInDev = "useLayoutEffect"; - updateHookTypesDev(); - return updateLayoutEffect(create, deps); - }, - useMemo: function (create, deps) { - currentHookNameInDev = "useMemo"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnRerenderInDEV; - - try { - return updateMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useReducer: function (reducer, initialArg, init) { - currentHookNameInDev = "useReducer"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnRerenderInDEV; + // This function is fork of reconcileChildren. It's used in cases where we + // want to reconcile without matching against the existing set. This has the + // effect of all current children being unmounted; even if the type and key + // are the same, the old child is unmounted and a new child is created. + // + // To do this, we're going to go through the reconcile algorithm twice. In + // the first pass, we schedule a deletion for all the current children by + // passing null. + workInProgress.child = reconcileChildFibers( + workInProgress, + current.child, + null, + renderLanes + ); // In the second pass, we mount the new children. The trick here is that we + // pass null in place of where we usually pass the current child set. This has + // the effect of remounting all children regardless of whether their + // identities match. - try { - return rerenderReducer(reducer, initialArg, init); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useRef: function (initialValue) { - currentHookNameInDev = "useRef"; - updateHookTypesDev(); - return updateRef(); - }, - useState: function (initialState) { - currentHookNameInDev = "useState"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnRerenderInDEV; + workInProgress.child = reconcileChildFibers( + workInProgress, + null, + nextChildren, + renderLanes + ); + } - try { - return rerenderState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function (value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - updateHookTypesDev(); - return updateDebugValue(); - }, - useDeferredValue: function (value, initialValue) { - currentHookNameInDev = "useDeferredValue"; - updateHookTypesDev(); - return rerenderDeferredValue(value, initialValue); - }, - useTransition: function () { - currentHookNameInDev = "useTransition"; - updateHookTypesDev(); - return rerenderTransition(); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - updateHookTypesDev(); - return updateId(); - } - }; - - { - HooksDispatcherOnRerenderInDEV.useCacheRefresh = - function useCacheRefresh() { - currentHookNameInDev = "useCacheRefresh"; - updateHookTypesDev(); - return updateRefresh(); - }; - } + function updateForwardRef( + current, + workInProgress, + Component, + nextProps, + renderLanes + ) { + // TODO: current can be non-null here even if the component + // hasn't yet mounted. This happens after the first render suspends. + // We'll need to figure out if this is fine or can cause issues. + { + if (workInProgress.type !== workInProgress.elementType) { + // Lazy component props can't be validated in createElement + // because they're only guaranteed to be resolved here. + var innerPropTypes = Component.propTypes; - { - HooksDispatcherOnRerenderInDEV.useMemoCache = useMemoCache; - } + if (innerPropTypes) { + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(Component) + ); + } + } + } - { - HooksDispatcherOnRerenderInDEV.useEffectEvent = function useEffectEvent( - callback - ) { - currentHookNameInDev = "useEffectEvent"; - updateHookTypesDev(); - return updateEvent(callback); - }; - } + var render = Component.render; + var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent - if (enableAsyncActions) { - HooksDispatcherOnRerenderInDEV.useOptimistic = function useOptimistic( - passthrough, - reducer - ) { - currentHookNameInDev = "useOptimistic"; - updateHookTypesDev(); - return rerenderOptimistic(passthrough, reducer); - }; - } - - InvalidNestedHooksDispatcherOnMountInDEV = { - readContext: function (context) { - warnInvalidContextAccess(); - return readContext(context); - }, - use: function (usable) { - warnInvalidHookAccess(); - return use(usable); - }, - useCallback: function (callback, deps) { - currentHookNameInDev = "useCallback"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountCallback(callback, deps); - }, - useContext: function (context) { - currentHookNameInDev = "useContext"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return readContext(context); - }, - useEffect: function (create, deps) { - currentHookNameInDev = "useEffect"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountEffect(create, deps); - }, - useImperativeHandle: function (ref, create, deps) { - currentHookNameInDev = "useImperativeHandle"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountImperativeHandle(ref, create, deps); - }, - useInsertionEffect: function (create, deps) { - currentHookNameInDev = "useInsertionEffect"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountInsertionEffect(create, deps); - }, - useLayoutEffect: function (create, deps) { - currentHookNameInDev = "useLayoutEffect"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountLayoutEffect(create, deps); - }, - useMemo: function (create, deps) { - currentHookNameInDev = "useMemo"; - warnInvalidHookAccess(); - mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + var nextChildren; + prepareToReadContext(workInProgress, renderLanes); - try { - return mountMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + if (enableSchedulingProfiler) { + markComponentRenderStarted(workInProgress); } - }, - useReducer: function (reducer, initialArg, init) { - currentHookNameInDev = "useReducer"; - warnInvalidHookAccess(); - mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; - - try { - return mountReducer(reducer, initialArg, init); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useRef: function (initialValue) { - currentHookNameInDev = "useRef"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountRef(initialValue); - }, - useState: function (initialState) { - currentHookNameInDev = "useState"; - warnInvalidHookAccess(); - mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; - try { - return mountState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function (value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountDebugValue(); - }, - useDeferredValue: function (value, initialValue) { - currentHookNameInDev = "useDeferredValue"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountDeferredValue(value, initialValue); - }, - useTransition: function () { - currentHookNameInDev = "useTransition"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountTransition(); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountId(); - } - }; - - { - InvalidNestedHooksDispatcherOnMountInDEV.useCacheRefresh = - function useCacheRefresh() { - currentHookNameInDev = "useCacheRefresh"; - mountHookTypesDev(); - return mountRefresh(); - }; - } + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + nextChildren = renderWithHooks( + current, + workInProgress, + render, + nextProps, + ref, + renderLanes + ); + setIsRendering(false); + } - { - InvalidNestedHooksDispatcherOnMountInDEV.useMemoCache = function (size) { - warnInvalidHookAccess(); - return useMemoCache(size); - }; - } - - { - InvalidNestedHooksDispatcherOnMountInDEV.useEffectEvent = - function useEffectEvent(callback) { - currentHookNameInDev = "useEffectEvent"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountEvent(callback); - }; - } - - if (enableAsyncActions) { - InvalidNestedHooksDispatcherOnMountInDEV.useOptimistic = - function useOptimistic(passthrough, reducer) { - currentHookNameInDev = "useOptimistic"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountOptimistic(passthrough); - }; - } - - InvalidNestedHooksDispatcherOnUpdateInDEV = { - readContext: function (context) { - warnInvalidContextAccess(); - return readContext(context); - }, - use: function (usable) { - warnInvalidHookAccess(); - return use(usable); - }, - useCallback: function (callback, deps) { - currentHookNameInDev = "useCallback"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateCallback(callback, deps); - }, - useContext: function (context) { - currentHookNameInDev = "useContext"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return readContext(context); - }, - useEffect: function (create, deps) { - currentHookNameInDev = "useEffect"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateEffect(create, deps); - }, - useImperativeHandle: function (ref, create, deps) { - currentHookNameInDev = "useImperativeHandle"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateImperativeHandle(ref, create, deps); - }, - useInsertionEffect: function (create, deps) { - currentHookNameInDev = "useInsertionEffect"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateInsertionEffect(create, deps); - }, - useLayoutEffect: function (create, deps) { - currentHookNameInDev = "useLayoutEffect"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateLayoutEffect(create, deps); - }, - useMemo: function (create, deps) { - currentHookNameInDev = "useMemo"; - warnInvalidHookAccess(); - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + if (enableSchedulingProfiler) { + markComponentRenderStopped(); + } - try { - return updateMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + if (current !== null && !didReceiveUpdate) { + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); } - }, - useReducer: function (reducer, initialArg, init) { - currentHookNameInDev = "useReducer"; - warnInvalidHookAccess(); - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; - try { - return updateReducer(reducer, initialArg, init); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useRef: function (initialValue) { - currentHookNameInDev = "useRef"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateRef(); - }, - useState: function (initialState) { - currentHookNameInDev = "useState"; - warnInvalidHookAccess(); - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } - try { - return updateState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function (value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateDebugValue(); - }, - useDeferredValue: function (value, initialValue) { - currentHookNameInDev = "useDeferredValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateDeferredValue(value, initialValue); - }, - useTransition: function () { - currentHookNameInDev = "useTransition"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateTransition(); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateId(); - } - }; - - { - InvalidNestedHooksDispatcherOnUpdateInDEV.useCacheRefresh = - function useCacheRefresh() { - currentHookNameInDev = "useCacheRefresh"; - updateHookTypesDev(); - return updateRefresh(); - }; - } + function updateMemoComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ) { + if (current === null) { + var type = Component.type; - { - InvalidNestedHooksDispatcherOnUpdateInDEV.useMemoCache = function (size) { - warnInvalidHookAccess(); - return useMemoCache(size); - }; - } - - { - InvalidNestedHooksDispatcherOnUpdateInDEV.useEffectEvent = - function useEffectEvent(callback) { - currentHookNameInDev = "useEffectEvent"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateEvent(callback); - }; - } - - if (enableAsyncActions) { - InvalidNestedHooksDispatcherOnUpdateInDEV.useOptimistic = - function useOptimistic(passthrough, reducer) { - currentHookNameInDev = "useOptimistic"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateOptimistic(passthrough, reducer); - }; - } - - InvalidNestedHooksDispatcherOnRerenderInDEV = { - readContext: function (context) { - warnInvalidContextAccess(); - return readContext(context); - }, - use: function (usable) { - warnInvalidHookAccess(); - return use(usable); - }, - useCallback: function (callback, deps) { - currentHookNameInDev = "useCallback"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateCallback(callback, deps); - }, - useContext: function (context) { - currentHookNameInDev = "useContext"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return readContext(context); - }, - useEffect: function (create, deps) { - currentHookNameInDev = "useEffect"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateEffect(create, deps); - }, - useImperativeHandle: function (ref, create, deps) { - currentHookNameInDev = "useImperativeHandle"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateImperativeHandle(ref, create, deps); - }, - useInsertionEffect: function (create, deps) { - currentHookNameInDev = "useInsertionEffect"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateInsertionEffect(create, deps); - }, - useLayoutEffect: function (create, deps) { - currentHookNameInDev = "useLayoutEffect"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateLayoutEffect(create, deps); - }, - useMemo: function (create, deps) { - currentHookNameInDev = "useMemo"; - warnInvalidHookAccess(); - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + if ( + isSimpleFunctionComponent(type) && + Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. + Component.defaultProps === undefined + ) { + var resolvedType = type; - try { - return updateMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useReducer: function (reducer, initialArg, init) { - currentHookNameInDev = "useReducer"; - warnInvalidHookAccess(); - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + { + resolvedType = resolveFunctionForHotReloading(type); + } // If this is a plain function component without default props, + // and with only the default shallow comparison, we upgrade it + // to a SimpleMemoComponent to allow fast path updates. - try { - return rerenderReducer(reducer, initialArg, init); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useRef: function (initialValue) { - currentHookNameInDev = "useRef"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateRef(); - }, - useState: function (initialState) { - currentHookNameInDev = "useState"; - warnInvalidHookAccess(); - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + workInProgress.tag = SimpleMemoComponent; + workInProgress.type = resolvedType; - try { - return rerenderState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function (value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateDebugValue(); - }, - useDeferredValue: function (value, initialValue) { - currentHookNameInDev = "useDeferredValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return rerenderDeferredValue(value, initialValue); - }, - useTransition: function () { - currentHookNameInDev = "useTransition"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return rerenderTransition(); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateId(); - } - }; - - { - InvalidNestedHooksDispatcherOnRerenderInDEV.useCacheRefresh = - function useCacheRefresh() { - currentHookNameInDev = "useCacheRefresh"; - updateHookTypesDev(); - return updateRefresh(); - }; - } + { + validateFunctionComponentInDev(workInProgress, type); + } - { - InvalidNestedHooksDispatcherOnRerenderInDEV.useMemoCache = function (size) { - warnInvalidHookAccess(); - return useMemoCache(size); - }; - } - - { - InvalidNestedHooksDispatcherOnRerenderInDEV.useEffectEvent = - function useEffectEvent(callback) { - currentHookNameInDev = "useEffectEvent"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateEvent(callback); - }; - } - - if (enableAsyncActions) { - InvalidNestedHooksDispatcherOnRerenderInDEV.useOptimistic = - function useOptimistic(passthrough, reducer) { - currentHookNameInDev = "useOptimistic"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return rerenderOptimistic(passthrough, reducer); - }; - } -} + return updateSimpleMemoComponent( + current, + workInProgress, + resolvedType, + nextProps, + renderLanes + ); + } -var now = Scheduler.unstable_now; -var commitTime = 0; -var layoutEffectStartTime = -1; -var profilerStartTime = -1; -var passiveEffectStartTime = -1; -/** - * Tracks whether the current update was a nested/cascading update (scheduled from a layout effect). - * - * The overall sequence is: - * 1. render - * 2. commit (and call `onRender`, `onCommit`) - * 3. check for nested updates - * 4. flush passive effects (and call `onPostCommit`) - * - * Nested updates are identified in step 3 above, - * but step 4 still applies to the work that was just committed. - * We use two flags to track nested updates then: - * one tracks whether the upcoming update is a nested update, - * and the other tracks whether the current update was a nested update. - * The first value gets synced to the second at the start of the render phase. - */ + { + var innerPropTypes = type.propTypes; -var currentUpdateIsNested = false; -var nestedUpdateScheduled = false; + if (innerPropTypes) { + // Inner memo component props aren't currently validated in createElement. + // We could move it there, but we'd still need this for lazy code path. + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(type) + ); + } -function isCurrentUpdateNested() { - return currentUpdateIsNested; -} + if (Component.defaultProps !== undefined) { + var componentName = getComponentNameFromType(type) || "Unknown"; -function markNestedUpdateScheduled() { - { - nestedUpdateScheduled = true; - } -} + if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) { + error( + "%s: Support for defaultProps will be removed from memo components " + + "in a future major release. Use JavaScript default parameters instead.", + componentName + ); -function resetNestedUpdateFlag() { - { - currentUpdateIsNested = false; - nestedUpdateScheduled = false; - } -} + didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true; + } + } + } -function syncNestedUpdateFlag() { - { - currentUpdateIsNested = nestedUpdateScheduled; - nestedUpdateScheduled = false; - } -} + var child = createFiberFromTypeAndProps( + Component.type, + null, + nextProps, + null, + workInProgress, + workInProgress.mode, + renderLanes + ); + child.ref = workInProgress.ref; + child.return = workInProgress; + workInProgress.child = child; + return child; + } -function getCommitTime() { - return commitTime; -} + { + var _type = Component.type; + var _innerPropTypes = _type.propTypes; -function recordCommitTime() { - commitTime = now(); -} + if (_innerPropTypes) { + // Inner memo component props aren't currently validated in createElement. + // We could move it there, but we'd still need this for lazy code path. + checkPropTypes( + _innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(_type) + ); + } + } -function startProfilerTimer(fiber) { - profilerStartTime = now(); + var currentChild = current.child; // This is always exactly one child - if (fiber.actualStartTime < 0) { - fiber.actualStartTime = now(); - } -} + var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( + current, + renderLanes + ); -function stopProfilerTimerIfRunning(fiber) { - profilerStartTime = -1; -} + if (!hasScheduledUpdateOrContext) { + // This will be the props with resolved defaultProps, + // unlike current.memoizedProps which will be the unresolved ones. + var prevProps = currentChild.memoizedProps; // Default to shallow comparison -function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { - if (profilerStartTime >= 0) { - var elapsedTime = now() - profilerStartTime; - fiber.actualDuration += elapsedTime; + var compare = Component.compare; + compare = compare !== null ? compare : shallowEqual; - if (overrideBaseTime) { - fiber.selfBaseDuration = elapsedTime; - } + if ( + compare(prevProps, nextProps) && + current.ref === workInProgress.ref + ) { + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + } + } // React DevTools reads this flag. - profilerStartTime = -1; - } -} + workInProgress.flags |= PerformedWork; + var newChild = createWorkInProgress(currentChild, nextProps); + newChild.ref = workInProgress.ref; + newChild.return = workInProgress; + workInProgress.child = newChild; + return newChild; + } -function recordLayoutEffectDuration(fiber) { - if (layoutEffectStartTime >= 0) { - var elapsedTime = now() - layoutEffectStartTime; - layoutEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor - // Or the root (for the DevTools Profiler to read) + function updateSimpleMemoComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ) { + // TODO: current can be non-null here even if the component + // hasn't yet mounted. This happens when the inner render suspends. + // We'll need to figure out if this is fine or can cause issues. + { + if (workInProgress.type !== workInProgress.elementType) { + // Lazy component props can't be validated in createElement + // because they're only guaranteed to be resolved here. + var outerMemoType = workInProgress.elementType; + + if (outerMemoType.$$typeof === REACT_LAZY_TYPE) { + // We warn when you define propTypes on lazy() + // so let's just skip over it to find memo() outer wrapper. + // Inner props for memo are validated later. + var lazyComponent = outerMemoType; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - var parentFiber = fiber.return; + try { + outerMemoType = init(payload); + } catch (x) { + outerMemoType = null; + } // Inner propTypes will be validated in the function component path. + + var outerPropTypes = outerMemoType && outerMemoType.propTypes; + + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + nextProps, // Resolved (SimpleMemoComponent has no defaultProps) + "prop", + getComponentNameFromType(outerMemoType) + ); + } + } + } + } - while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; - root.effectDuration += elapsedTime; - return; + if (current !== null) { + var prevProps = current.memoizedProps; - case Profiler: - var parentStateNode = parentFiber.stateNode; - parentStateNode.effectDuration += elapsedTime; - return; + if ( + shallowEqual(prevProps, nextProps) && + current.ref === workInProgress.ref && // Prevent bailout if the implementation changed due to hot reload. + workInProgress.type === current.type + ) { + didReceiveUpdate = false; // The props are shallowly equal. Reuse the previous props object, like we + // would during a normal fiber bailout. + // + // We don't have strong guarantees that the props object is referentially + // equal during updates where we can't bail out anyway — like if the props + // are shallowly equal, but there's a local state or context update in the + // same batch. + // + // However, as a principle, we should aim to make the behavior consistent + // across different ways of memoizing a component. For example, React.memo + // has a different internal Fiber layout if you pass a normal function + // component (SimpleMemoComponent) versus if you pass a different type + // like forwardRef (MemoComponent). But this is an implementation detail. + // Wrapping a component in forwardRef (or React.lazy, etc) shouldn't + // affect whether the props object is reused during a bailout. + + workInProgress.pendingProps = nextProps = prevProps; + + if (!checkScheduledUpdateOrContext(current, renderLanes)) { + // The pending lanes were cleared at the beginning of beginWork. We're + // about to bail out, but there might be other lanes that weren't + // included in the current render. Usually, the priority level of the + // remaining updates is accumulated during the evaluation of the + // component (i.e. when processing the update queue). But since since + // we're bailing out early *without* evaluating the component, we need + // to account for it here, too. Reset to the value of the current fiber. + // NOTE: This only applies to SimpleMemoComponent, not MemoComponent, + // because a MemoComponent fiber does not have hooks or an update queue; + // rather, it wraps around an inner component, which may or may not + // contains hooks. + // TODO: Move the reset at in beginWork out of the common path so that + // this is no longer necessary. + workInProgress.lanes = current.lanes; + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + } else if ( + (current.flags & ForceUpdateForLegacySuspense) !== + NoFlags$1 + ) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; + } + } } - parentFiber = parentFiber.return; + return updateFunctionComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ); } - } -} -function recordPassiveEffectDuration(fiber) { - if (passiveEffectStartTime >= 0) { - var elapsedTime = now() - passiveEffectStartTime; - passiveEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor - // Or the root (for the DevTools Profiler to read) + function updateOffscreenComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + var nextIsDetached = + (workInProgress.stateNode._pendingVisibility & OffscreenDetached) !== 0; + var prevState = current !== null ? current.memoizedState : null; + markRef$1(current, workInProgress); - var parentFiber = fiber.return; + if ( + nextProps.mode === "hidden" || + nextProps.mode === "unstable-defer-without-hiding" || + nextIsDetached + ) { + // Rendering a hidden tree. + var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags$1; - while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; + if (didSuspend) { + // Something suspended inside a hidden tree + // Include the base lanes from the last render + var nextBaseLanes = + prevState !== null + ? mergeLanes(prevState.baseLanes, renderLanes) + : renderLanes; - if (root !== null) { - root.passiveEffectDuration += elapsedTime; + if (current !== null) { + // Reset to the current children + var currentChild = (workInProgress.child = current.child); // The current render suspended, but there may be other lanes with + // pending work. We can't read `childLanes` from the current Offscreen + // fiber because we reset it when it was deferred; however, we can read + // the pending lanes from the child fibers. + + var currentChildLanes = NoLanes; + + while (currentChild !== null) { + currentChildLanes = mergeLanes( + mergeLanes(currentChildLanes, currentChild.lanes), + currentChild.childLanes + ); + currentChild = currentChild.sibling; + } + + var lanesWeJustAttempted = nextBaseLanes; + var remainingChildLanes = removeLanes( + currentChildLanes, + lanesWeJustAttempted + ); + workInProgress.childLanes = remainingChildLanes; + } else { + workInProgress.childLanes = NoLanes; + workInProgress.child = null; } - return; + return deferHiddenOffscreenComponent( + current, + workInProgress, + nextBaseLanes, + renderLanes + ); + } - case Profiler: - var parentStateNode = parentFiber.stateNode; + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + // In legacy sync mode, don't defer the subtree. Render it now. + // TODO: Consider how Offscreen should work with transitions in the future + var nextState = { + baseLanes: NoLanes, + cachePool: null + }; + workInProgress.memoizedState = nextState; - if (parentStateNode !== null) { - // Detached fibers have their state node cleared out. - // In this case, the return pointer is also cleared out, - // so we won't be able to report the time spent in this Profiler's subtree. - parentStateNode.passiveEffectDuration += elapsedTime; + { + // push the cache pool even though we're going to bail out + // because otherwise there'd be a context mismatch + if (current !== null) { + pushTransition(workInProgress, null, null); + } } - return; - } + reuseHiddenContextOnStack(workInProgress); + pushOffscreenSuspenseHandler(workInProgress); + } else if (!includesSomeLane(renderLanes, OffscreenLane)) { + // We're hidden, and we're not rendering at Offscreen. We will bail out + // and resume this tree later. + // Schedule this fiber to re-render at Offscreen priority + workInProgress.lanes = workInProgress.childLanes = + laneToLanes(OffscreenLane); // Include the base lanes from the last render + + var _nextBaseLanes = + prevState !== null + ? mergeLanes(prevState.baseLanes, renderLanes) + : renderLanes; + + return deferHiddenOffscreenComponent( + current, + workInProgress, + _nextBaseLanes, + renderLanes + ); + } else { + // This is the second render. The surrounding visible content has already + // committed. Now we resume rendering the hidden tree. + // Rendering at offscreen, so we can clear the base lanes. + var _nextState = { + baseLanes: NoLanes, + cachePool: null + }; + workInProgress.memoizedState = _nextState; - parentFiber = parentFiber.return; - } - } -} + if (current !== null) { + // If the render that spawned this one accessed the cache pool, resume + // using the same cache. Unless the parent changed, since that means + // there was a refresh. + var prevCachePool = prevState !== null ? prevState.cachePool : null; // TODO: Consider if and how Offscreen pre-rendering should + // be attributed to the transition that spawned it -function startLayoutEffectTimer() { - layoutEffectStartTime = now(); -} + pushTransition(workInProgress, prevCachePool, null); + } // Push the lanes that were skipped when we bailed out. -function startPassiveEffectTimer() { - passiveEffectStartTime = now(); -} + if (prevState !== null) { + pushHiddenContext(workInProgress, prevState); + } else { + reuseHiddenContextOnStack(workInProgress); + } -function transferActualDuration(fiber) { - // Transfer time spent rendering these children so we don't lose it - // after we rerender. This is used as a helper in special cases - // where we should count the work of multiple passes. - var child = fiber.child; - - while (child) { - // $FlowFixMe[unsafe-addition] addition with possible null/undefined value - fiber.actualDuration += child.actualDuration; - child = child.sibling; - } -} + pushOffscreenSuspenseHandler(workInProgress); + } + } else { + // Rendering a visible tree. + if (prevState !== null) { + // We're going from hidden -> visible. + var _prevCachePool = null; -function resolveDefaultProps(Component, baseProps) { - if (Component && Component.defaultProps) { - // Resolve default props. Taken from ReactElement - var props = assign({}, baseProps); - var defaultProps = Component.defaultProps; + { + // If the render that spawned this one accessed the cache pool, resume + // using the same cache. Unless the parent changed, since that means + // there was a refresh. + _prevCachePool = prevState.cachePool; + } - for (var propName in defaultProps) { - if (props[propName] === undefined) { - props[propName] = defaultProps[propName]; - } - } + var transitions = null; - return props; - } + if (enableTransitionTracing) { + // We have now gone from hidden to visible, so any transitions should + // be added to the stack to get added to any Offscreen/suspense children + var instance = workInProgress.stateNode; - return baseProps; -} + if (instance !== null && instance._transitions != null) { + transitions = Array.from(instance._transitions); + } + } -var fakeInternalInstance = {}; -var didWarnAboutStateAssignmentForComponent; -var didWarnAboutUninitializedState; -var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate; -var didWarnAboutLegacyLifecyclesAndDerivedState; -var didWarnAboutUndefinedDerivedState; -var didWarnAboutDirectlyAssigningPropsToState; -var didWarnAboutContextTypeAndContextTypes; -var didWarnAboutInvalidateContextType; -var didWarnOnInvalidCallback; - -{ - didWarnAboutStateAssignmentForComponent = new Set(); - didWarnAboutUninitializedState = new Set(); - didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set(); - didWarnAboutLegacyLifecyclesAndDerivedState = new Set(); - didWarnAboutDirectlyAssigningPropsToState = new Set(); - didWarnAboutUndefinedDerivedState = new Set(); - didWarnAboutContextTypeAndContextTypes = new Set(); - didWarnAboutInvalidateContextType = new Set(); - didWarnOnInvalidCallback = new Set(); // This is so gross but it's at least non-critical and can be removed if - // it causes problems. This is meant to give a nicer error message for - // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component, - // ...)) which otherwise throws a "_processChildContext is not a function" - // exception. - - Object.defineProperty(fakeInternalInstance, "_processChildContext", { - enumerable: false, - value: function () { - 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)." - ); - } - }); - Object.freeze(fakeInternalInstance); -} + pushTransition(workInProgress, _prevCachePool, transitions); // Push the lanes that were skipped when we bailed out. -function warnOnInvalidCallback(callback, callerName) { - { - if (callback === null || typeof callback === "function") { - return; - } + pushHiddenContext(workInProgress, prevState); + reuseSuspenseHandlerOnStack(workInProgress); // Since we're not hidden anymore, reset the state - var key = callerName + "_" + callback; + workInProgress.memoizedState = null; + } else { + // We weren't previously hidden, and we still aren't, so there's nothing + // special to do. Need to push to the stack regardless, though, to avoid + // a push/pop misalignment. + { + // If the render that spawned this one accessed the cache pool, resume + // using the same cache. Unless the parent changed, since that means + // there was a refresh. + if (current !== null) { + pushTransition(workInProgress, null, null); + } + } // We're about to bail out, but we need to push this to the stack anyway + // to avoid a push/pop misalignment. - if (!didWarnOnInvalidCallback.has(key)) { - didWarnOnInvalidCallback.add(key); + reuseHiddenContextOnStack(workInProgress); + reuseSuspenseHandlerOnStack(workInProgress); + } + } - error( - "%s(...): Expected the last optional `callback` argument to be a " + - "function. Instead received: %s.", - callerName, - callback - ); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - } -} - -function warnOnUndefinedDerivedState(type, partialState) { - { - if (partialState === undefined) { - var componentName = getComponentNameFromType(type) || "Component"; - if (!didWarnAboutUndefinedDerivedState.has(componentName)) { - didWarnAboutUndefinedDerivedState.add(componentName); - - error( - "%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. " + - "You have returned undefined.", - componentName - ); - } - } - } -} + function deferHiddenOffscreenComponent( + current, + workInProgress, + nextBaseLanes, + renderLanes + ) { + var nextState = { + baseLanes: nextBaseLanes, + // Save the cache pool so we can resume later. + cachePool: getOffscreenDeferredCache() + }; + workInProgress.memoizedState = nextState; -function applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - nextProps -) { - var prevState = workInProgress.memoizedState; - var partialState = getDerivedStateFromProps(nextProps, prevState); + { + // push the cache pool even though we're going to bail out + // because otherwise there'd be a context mismatch + if (current !== null) { + pushTransition(workInProgress, null, null); + } + } // We're about to bail out, but we need to push this to the stack anyway + // to avoid a push/pop misalignment. - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + reuseHiddenContextOnStack(workInProgress); + pushOffscreenSuspenseHandler(workInProgress); - try { - // Invoke the function an extra time to help detect side-effects. - partialState = getDerivedStateFromProps(nextProps, prevState); - } finally { - setIsStrictModeForDevtools(false); + if (enableLazyContextPropagation && current !== null) { + // Since this tree will resume rendering in a separate render, we need + // to propagate parent contexts now so we don't lose track of which + // ones changed. + propagateParentContextChangesToDeferredTree( + current, + workInProgress, + renderLanes + ); } - } - - warnOnUndefinedDerivedState(ctor, partialState); - } // Merge the partial state and the previous state. - - var memoizedState = - partialState === null || partialState === undefined - ? prevState - : assign({}, prevState, partialState); - workInProgress.memoizedState = memoizedState; // Once the update queue is empty, persist the derived state onto the - // base state. - if (workInProgress.lanes === NoLanes) { - // Queue is always non-null for classes - var updateQueue = workInProgress.updateQueue; - updateQueue.baseState = memoizedState; - } -} + return null; + } // Note: These happen to have identical begin phases, for now. We shouldn't hold + // ourselves to this constraint, though. If the behavior diverges, we should + // fork the function. -var classComponentUpdater = { - isMounted: isMounted, - // $FlowFixMe[missing-local-annot] - enqueueSetState: function (inst, payload, callback) { - var fiber = get(inst); - var lane = requestUpdateLane(fiber); - var update = createUpdate(lane); - update.payload = payload; + var updateLegacyHiddenComponent = updateOffscreenComponent; - if (callback !== undefined && callback !== null) { - { - warnOnInvalidCallback(callback, "setState"); - } + function updateCacheComponent(current, workInProgress, renderLanes) { + prepareToReadContext(workInProgress, renderLanes); + var parentCache = readContext(CacheContext); - update.callback = callback; - } + if (current === null) { + // Initial mount. Request a fresh cache from the pool. + var freshCache = requestCacheFromPool(renderLanes); + var initialState = { + parent: parentCache, + cache: freshCache + }; + workInProgress.memoizedState = initialState; + initializeUpdateQueue(workInProgress); + pushCacheProvider(workInProgress, freshCache); + } else { + // Check for updates + if (includesSomeLane(current.lanes, renderLanes)) { + cloneUpdateQueue(current, workInProgress); + processUpdateQueue(workInProgress, null, null, renderLanes); + } - var root = enqueueUpdate(fiber, update, lane); + var prevState = current.memoizedState; + var nextState = workInProgress.memoizedState; // Compare the new parent cache to the previous to see detect there was + // a refresh. + + if (prevState.parent !== parentCache) { + // Refresh in parent. Update the parent. + var derivedState = { + parent: parentCache, + cache: parentCache + }; // Copied from getDerivedStateFromProps implementation. Once the update + // queue is empty, persist the derived state onto the base state. + + workInProgress.memoizedState = derivedState; + + if (workInProgress.lanes === NoLanes) { + var updateQueue = workInProgress.updateQueue; + workInProgress.memoizedState = updateQueue.baseState = derivedState; + } - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane); - entangleTransitions(root, fiber, lane); - } + pushCacheProvider(workInProgress, parentCache); // No need to propagate a context change because the refreshed parent + // already did. + } else { + // The parent didn't refresh. Now check if this cache did. + var nextCache = nextState.cache; + pushCacheProvider(workInProgress, nextCache); - { - if (enableDebugTracing) { - if (fiber.mode & DebugTracingMode) { - var name = getComponentNameFromFiber(fiber) || "Unknown"; - logStateUpdateScheduled(name, lane, payload); + if (nextCache !== prevState.cache) { + // This cache refreshed. Propagate a context change. + propagateContextChange(workInProgress, CacheContext, renderLanes); + } } } - } - - if (enableSchedulingProfiler) { - markStateUpdateScheduled(fiber, lane); - } - }, - enqueueReplaceState: function (inst, payload, callback) { - var fiber = get(inst); - var lane = requestUpdateLane(fiber); - var update = createUpdate(lane); - update.tag = ReplaceState; - update.payload = payload; - if (callback !== undefined && callback !== null) { - { - warnOnInvalidCallback(callback, "replaceState"); - } + var nextChildren = workInProgress.pendingProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } // This should only be called if the name changes - update.callback = callback; - } + function updateTracingMarkerComponent( + current, + workInProgress, + renderLanes + ) { + if (!enableTransitionTracing) { + return null; + } // TODO: (luna) Only update the tracing marker if it's newly rendered or it's name changed. + // A tracing marker is only associated with the transitions that rendered + // or updated it, so we can create a new set of transitions each time - var root = enqueueUpdate(fiber, update, lane); + if (current === null) { + var currentTransitions = getPendingTransitions(); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane); - entangleTransitions(root, fiber, lane); - } + if (currentTransitions !== null) { + var markerInstance = { + tag: TransitionTracingMarker, + transitions: new Set(currentTransitions), + pendingBoundaries: null, + name: workInProgress.pendingProps.name, + aborts: null + }; + workInProgress.stateNode = markerInstance; // We call the marker complete callback when all child suspense boundaries resolve. + // We do this in the commit phase on Offscreen. If the marker has no child suspense + // boundaries, we need to schedule a passive effect to make sure we call the marker + // complete callback. - { - if (enableDebugTracing) { - if (fiber.mode & DebugTracingMode) { - var name = getComponentNameFromFiber(fiber) || "Unknown"; - logStateUpdateScheduled(name, lane, payload); + workInProgress.flags |= Passive$1; + } + } else { + { + if (current.memoizedProps.name !== workInProgress.pendingProps.name) { + error( + "Changing the name of a tracing marker after mount is not supported. " + + "To remount the tracing marker, pass it a new key." + ); + } } } - } - if (enableSchedulingProfiler) { - markStateUpdateScheduled(fiber, lane); - } - }, - // $FlowFixMe[missing-local-annot] - enqueueForceUpdate: function (inst, callback) { - var fiber = get(inst); - var lane = requestUpdateLane(fiber); - var update = createUpdate(lane); - update.tag = ForceUpdate; + var instance = workInProgress.stateNode; - if (callback !== undefined && callback !== null) { - { - warnOnInvalidCallback(callback, "forceUpdate"); + if (instance !== null) { + pushMarkerInstance(workInProgress, instance); } - update.callback = callback; + var nextChildren = workInProgress.pendingProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - var root = enqueueUpdate(fiber, update, lane); + function updateFragment(current, workInProgress, renderLanes) { + var nextChildren = workInProgress.pendingProps; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane); - entangleTransitions(root, fiber, lane); + function updateMode(current, workInProgress, renderLanes) { + var nextChildren = workInProgress.pendingProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - { - if (enableDebugTracing) { - if (fiber.mode & DebugTracingMode) { - var name = getComponentNameFromFiber(fiber) || "Unknown"; - logForceUpdateScheduled(name, lane); + function updateProfiler(current, workInProgress, renderLanes) { + { + workInProgress.flags |= Update; + + { + // Reset effect durations for the next eventual effect phase. + // These are reset during render to allow the DevTools commit hook a chance to read them, + var stateNode = workInProgress.stateNode; + stateNode.effectDuration = 0; + stateNode.passiveEffectDuration = 0; } } - } - if (enableSchedulingProfiler) { - markForceUpdateScheduled(fiber, lane); + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - } -}; -function checkShouldComponentUpdate( - workInProgress, - ctor, - oldProps, - newProps, - oldState, - newState, - nextContext -) { - var instance = workInProgress.stateNode; + function markRef$1(current, workInProgress) { + var ref = workInProgress.ref; - if (typeof instance.shouldComponentUpdate === "function") { - var shouldUpdate = instance.shouldComponentUpdate( - newProps, - newState, - nextContext - ); + if ( + (current === null && ref !== null) || + (current !== null && current.ref !== ref) + ) { + // Schedule a Ref effect + workInProgress.flags |= Ref; + workInProgress.flags |= RefStatic; + } + } - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + function updateFunctionComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ) { + { + if (workInProgress.type !== workInProgress.elementType) { + // Lazy component props can't be validated in createElement + // because they're only guaranteed to be resolved here. + var innerPropTypes = Component.propTypes; - try { - // Invoke the function an extra time to help detect side-effects. - shouldUpdate = instance.shouldComponentUpdate( - newProps, - newState, - nextContext - ); - } finally { - setIsStrictModeForDevtools(false); + if (innerPropTypes) { + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(Component) + ); + } } } - if (shouldUpdate === undefined) { - error( - "%s.shouldComponentUpdate(): Returned undefined instead of a " + - "boolean value. Make sure to return true or false.", - getComponentNameFromType(ctor) || "Component" + var context; + + { + var unmaskedContext = getUnmaskedContext( + workInProgress, + Component, + true ); + context = getMaskedContext(workInProgress, unmaskedContext); } - } - - return shouldUpdate; - } - if (ctor.prototype && ctor.prototype.isPureReactComponent) { - return ( - !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) - ); - } + var nextChildren; + prepareToReadContext(workInProgress, renderLanes); - return true; -} + if (enableSchedulingProfiler) { + markComponentRenderStarted(workInProgress); + } -function checkClassInstance(workInProgress, ctor, newProps) { - var instance = workInProgress.stateNode; + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + nextChildren = renderWithHooks( + current, + workInProgress, + Component, + nextProps, + context, + renderLanes + ); + setIsRendering(false); + } - { - var name = getComponentNameFromType(ctor) || "Component"; - var renderPresent = instance.render; + if (enableSchedulingProfiler) { + markComponentRenderStopped(); + } - if (!renderPresent) { - if (ctor.prototype && typeof ctor.prototype.render === "function") { - error( - "%s(...): No `render` method found on the returned component " + - "instance: did you accidentally return an object from the constructor?", - name - ); - } else { - error( - "%s(...): No `render` method found on the returned component " + - "instance: you may have forgotten to define `render`.", - name + if (current !== null && !didReceiveUpdate) { + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes ); } - } - if ( - instance.getInitialState && - !instance.getInitialState.isReactClassApproved && - !instance.state - ) { - 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 - ); + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - if ( - instance.getDefaultProps && - !instance.getDefaultProps.isReactClassApproved + function replayFunctionComponent( + current, + workInProgress, + nextProps, + Component, + secondArg, + renderLanes ) { - 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 - ); - } + // This function is used to replay a component that previously suspended, + // after its data resolves. It's a simplified version of + // updateFunctionComponent that reuses the hooks from the previous attempt. + prepareToReadContext(workInProgress, renderLanes); - if (instance.propTypes) { - error( - "propTypes was defined as an instance property on %s. Use a static " + - "property to define propTypes instead.", - name - ); - } + if (enableSchedulingProfiler) { + markComponentRenderStarted(workInProgress); + } - if (instance.contextType) { - error( - "contextType was defined as an instance property on %s. Use a static " + - "property to define contextType instead.", - name + var nextChildren = replaySuspendedComponentWithHooks( + current, + workInProgress, + Component, + nextProps, + secondArg ); - } - { - if (instance.contextTypes) { - error( - "contextTypes was defined as an instance property on %s. Use a static " + - "property to define contextTypes instead.", - name - ); + if (enableSchedulingProfiler) { + markComponentRenderStopped(); } - if ( - ctor.contextType && - ctor.contextTypes && - !didWarnAboutContextTypeAndContextTypes.has(ctor) - ) { - didWarnAboutContextTypeAndContextTypes.add(ctor); - - error( - "%s declares both contextTypes and contextType static properties. " + - "The legacy contextTypes property will be ignored.", - name + if (current !== null && !didReceiveUpdate) { + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes ); } - } - if (typeof instance.componentShouldUpdate === "function") { - 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 - ); + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - if ( - ctor.prototype && - ctor.prototype.isPureReactComponent && - typeof instance.shouldComponentUpdate !== "undefined" + function updateClassComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes ) { - 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" - ); - } + { + // This is used by DevTools to force a boundary to error. + switch (shouldError(workInProgress)) { + case false: { + var _instance = workInProgress.stateNode; + var ctor = workInProgress.type; // TODO This way of resetting the error boundary state is a hack. + // Is there a better way to do this? + + var tempInstance = new ctor( + workInProgress.memoizedProps, + _instance.context + ); + var state = tempInstance.state; - if (typeof instance.componentDidUnmount === "function") { - error( - "%s has a method called " + - "componentDidUnmount(). But there is no such lifecycle method. " + - "Did you mean componentWillUnmount()?", - name - ); - } + _instance.updater.enqueueSetState(_instance, state, null); - if (typeof instance.componentDidReceiveProps === "function") { - 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 - ); - } + break; + } - if (typeof instance.componentWillRecieveProps === "function") { - error( - "%s has a method called " + - "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", - name - ); - } + case true: { + workInProgress.flags |= DidCapture; + workInProgress.flags |= ShouldCapture; // eslint-disable-next-line react-internal/prod-error-codes - if (typeof instance.UNSAFE_componentWillRecieveProps === "function") { - error( - "%s has a method called " + - "UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?", - name - ); - } + var error$1 = new Error("Simulated error coming from DevTools"); + var lane = pickArbitraryLane(renderLanes); + workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); // Schedule the error boundary to re-render using updated state - var hasMutatedProps = instance.props !== newProps; + var update = createClassErrorUpdate( + workInProgress, + createCapturedValueAtFiber(error$1, workInProgress), + lane + ); + enqueueCapturedUpdate(workInProgress, update); + break; + } + } - if (instance.props !== undefined && hasMutatedProps) { - error( - "%s(...): When calling super() in `%s`, make sure to pass " + - "up the same props that your component's constructor was passed.", - name, - name - ); - } + if (workInProgress.type !== workInProgress.elementType) { + // Lazy component props can't be validated in createElement + // because they're only guaranteed to be resolved here. + var innerPropTypes = Component.propTypes; - if (instance.defaultProps) { - 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 - ); - } + if (innerPropTypes) { + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(Component) + ); + } + } + } // Push context providers early to prevent context stack mismatches. + // During mounting we don't know the child context yet as the instance doesn't exist. + // We will invalidate the child context in finishClassComponent() right after rendering. - if ( - typeof instance.getSnapshotBeforeUpdate === "function" && - typeof instance.componentDidUpdate !== "function" && - !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor) - ) { - didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor); + var hasContext; - error( - "%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). " + - "This component defines getSnapshotBeforeUpdate() only.", - getComponentNameFromType(ctor) - ); - } + if (isContextProvider(Component)) { + hasContext = true; + pushContextProvider(workInProgress); + } else { + hasContext = false; + } - if (typeof instance.getDerivedStateFromProps === "function") { - error( - "%s: getDerivedStateFromProps() is defined as an instance method " + - "and will be ignored. Instead, declare it as a static method.", - name - ); - } + prepareToReadContext(workInProgress, renderLanes); + var instance = workInProgress.stateNode; + var shouldUpdate; - if (typeof instance.getDerivedStateFromError === "function") { - error( - "%s: getDerivedStateFromError() is defined as an instance method " + - "and will be ignored. Instead, declare it as a static method.", - name - ); - } + if (instance === null) { + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); // In the initial pass we might need to construct the instance. + + constructClassInstance(workInProgress, Component, nextProps); + mountClassInstance(workInProgress, Component, nextProps, renderLanes); + shouldUpdate = true; + } else if (current === null) { + // In a resume, we'll already have an instance we can reuse. + shouldUpdate = resumeMountClassInstance( + workInProgress, + Component, + nextProps, + renderLanes + ); + } else { + shouldUpdate = updateClassInstance( + current, + workInProgress, + Component, + nextProps, + renderLanes + ); + } - if (typeof ctor.getSnapshotBeforeUpdate === "function") { - error( - "%s: getSnapshotBeforeUpdate() is defined as a static method " + - "and will be ignored. Instead, declare it as an instance method.", - name + var nextUnitOfWork = finishClassComponent( + current, + workInProgress, + Component, + shouldUpdate, + hasContext, + renderLanes ); - } - var state = instance.state; + { + var inst = workInProgress.stateNode; + + if (shouldUpdate && inst.props !== nextProps) { + if (!didWarnAboutReassigningProps) { + 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" + ); + } + + didWarnAboutReassigningProps = true; + } + } - if (state && (typeof state !== "object" || isArray(state))) { - error("%s.state: must be set to an object or null", name); + return nextUnitOfWork; } - if ( - typeof instance.getChildContext === "function" && - typeof ctor.childContextTypes !== "object" + function finishClassComponent( + current, + workInProgress, + Component, + shouldUpdate, + hasContext, + renderLanes ) { - error( - "%s.getChildContext(): childContextTypes must be defined in order to " + - "use getChildContext().", - name - ); - } - } -} + // Refs should update even if shouldComponentUpdate returns false + markRef$1(current, workInProgress); + var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags$1; + + if (!shouldUpdate && !didCaptureError) { + // Context providers should defer to sCU for rendering + if (hasContext) { + invalidateContextProvider(workInProgress, Component, false); + } + + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + } -function adoptClassInstance(workInProgress, instance) { - instance.updater = classComponentUpdater; - workInProgress.stateNode = instance; // The instance needs access to the fiber so that it can schedule updates + var instance = workInProgress.stateNode; // Rerender - set(instance, workInProgress); + ReactCurrentOwner$1.current = workInProgress; + var nextChildren; - { - instance._reactInternalInstance = fakeInternalInstance; - } -} + if ( + didCaptureError && + typeof Component.getDerivedStateFromError !== "function" + ) { + // If we captured an error, but getDerivedStateFromError is not defined, + // unmount all the children. componentDidCatch will schedule an update to + // re-render a fallback. This is temporary until we migrate everyone to + // the new API. + // TODO: Warn in a future release. + nextChildren = null; + + { + stopProfilerTimerIfRunning(); + } + } else { + if (enableSchedulingProfiler) { + markComponentRenderStarted(workInProgress); + } + + { + setIsRendering(true); + nextChildren = instance.render(); + + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); + + try { + instance.render(); + } finally { + setIsStrictModeForDevtools(false); + } + } -function constructClassInstance(workInProgress, ctor, props) { - var isLegacyContextConsumer = false; - var unmaskedContext = emptyContextObject; - var context = emptyContextObject; - var contextType = ctor.contextType; - - { - if ("contextType" in ctor) { - var isValid = // Allow null for conditional declaration - contextType === null || - (contextType !== undefined && - contextType.$$typeof === REACT_CONTEXT_TYPE && - contextType._context === undefined); // Not a - - if (!isValid && !didWarnAboutInvalidateContextType.has(ctor)) { - didWarnAboutInvalidateContextType.add(ctor); - var addendum = ""; - - if (contextType === undefined) { - 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."; - } else if (typeof contextType !== "object") { - addendum = " However, it is set to a " + typeof contextType + "."; - } else if (contextType.$$typeof === REACT_PROVIDER_TYPE) { - addendum = " Did you accidentally pass the Context.Provider instead?"; - } else if (contextType._context !== undefined) { - // - addendum = " Did you accidentally pass the Context.Consumer instead?"; - } else { - addendum = - " However, it is set to an object with keys {" + - Object.keys(contextType).join(", ") + - "}."; + setIsRendering(false); } - error( - "%s defines an invalid contextType. " + - "contextType should point to the Context object returned by React.createContext().%s", - getComponentNameFromType(ctor) || "Component", - addendum - ); - } - } - } + if (enableSchedulingProfiler) { + markComponentRenderStopped(); + } + } // React DevTools reads this flag. - if (typeof contextType === "object" && contextType !== null) { - context = readContext(contextType); - } else { - unmaskedContext = getUnmaskedContext(workInProgress, ctor, true); - var contextTypes = ctor.contextTypes; - isLegacyContextConsumer = - contextTypes !== null && contextTypes !== undefined; - context = isLegacyContextConsumer - ? getMaskedContext(workInProgress, unmaskedContext) - : emptyContextObject; - } + workInProgress.flags |= PerformedWork; - var instance = new ctor(props, context); // Instantiate twice to help detect side-effects. + if (current !== null && didCaptureError) { + // If we're recovering from an error, reconcile without reusing any of + // the existing children. Conceptually, the normal children and the children + // that are shown on error are two different sets, so we shouldn't reuse + // normal children even if their identities match. + forceUnmountCurrentAndReconcile( + current, + workInProgress, + nextChildren, + renderLanes + ); + } else { + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + } // Memoize state using the values we just used to render. + // TODO: Restructure so we never read values from the instance. - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + workInProgress.memoizedState = instance.state; // The context might have changed so we need to recalculate it. - try { - instance = new ctor(props, context); // eslint-disable-line no-new - } finally { - setIsStrictModeForDevtools(false); + if (hasContext) { + invalidateContextProvider(workInProgress, Component, true); } - } - } - - var state = (workInProgress.memoizedState = - instance.state !== null && instance.state !== undefined - ? instance.state - : null); - adoptClassInstance(workInProgress, instance); - { - if (typeof ctor.getDerivedStateFromProps === "function" && state === null) { - var componentName = getComponentNameFromType(ctor) || "Component"; + return workInProgress.child; + } - if (!didWarnAboutUninitializedState.has(componentName)) { - didWarnAboutUninitializedState.add(componentName); + function pushHostRootContext(workInProgress) { + var root = workInProgress.stateNode; - 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 + if (root.pendingContext) { + pushTopLevelContextObject( + workInProgress, + root.pendingContext, + root.pendingContext !== root.context ); + } else if (root.context) { + // Should always be set + pushTopLevelContextObject(workInProgress, root.context, false); } - } // If new component APIs are defined, "unsafe" lifecycles won't be called. - // Warn about these lifecycles if they are present. - // Don't warn about react-lifecycles-compat polyfilled methods though. - if ( - typeof ctor.getDerivedStateFromProps === "function" || - typeof instance.getSnapshotBeforeUpdate === "function" - ) { - var foundWillMountName = null; - var foundWillReceivePropsName = null; - var foundWillUpdateName = null; + pushHostContainer(workInProgress, root.containerInfo); + } - if ( - typeof instance.componentWillMount === "function" && - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - foundWillMountName = "componentWillMount"; - } else if (typeof instance.UNSAFE_componentWillMount === "function") { - foundWillMountName = "UNSAFE_componentWillMount"; - } + function updateHostRoot(current, workInProgress, renderLanes) { + pushHostRootContext(workInProgress); - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== true - ) { - foundWillReceivePropsName = "componentWillReceiveProps"; - } else if ( - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - foundWillReceivePropsName = "UNSAFE_componentWillReceiveProps"; + if (current === null) { + throw new Error("Should have a current fiber. This is a bug in React."); } - if ( - typeof instance.componentWillUpdate === "function" && - instance.componentWillUpdate.__suppressDeprecationWarning !== true - ) { - foundWillUpdateName = "componentWillUpdate"; - } else if (typeof instance.UNSAFE_componentWillUpdate === "function") { - foundWillUpdateName = "UNSAFE_componentWillUpdate"; + var nextProps = workInProgress.pendingProps; + var prevState = workInProgress.memoizedState; + var prevChildren = prevState.element; + cloneUpdateQueue(current, workInProgress); + processUpdateQueue(workInProgress, nextProps, null, renderLanes); + var nextState = workInProgress.memoizedState; + pushRootTransition(workInProgress); + + if (enableTransitionTracing) { + pushRootMarkerInstance(workInProgress); } - if ( - foundWillMountName !== null || - foundWillReceivePropsName !== null || - foundWillUpdateName !== null - ) { - var _componentName = getComponentNameFromType(ctor) || "Component"; + { + var nextCache = nextState.cache; + pushCacheProvider(workInProgress, nextCache); - var newApiName = - typeof ctor.getDerivedStateFromProps === "function" - ? "getDerivedStateFromProps()" - : "getSnapshotBeforeUpdate()"; + if (nextCache !== prevState.cache) { + // The root cache refreshed. + propagateContextChange(workInProgress, CacheContext, renderLanes); + } + } // Caution: React DevTools currently depends on this property + // being called "element". - if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName)) { - didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName); + var nextChildren = nextState.element; - 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 : "" + { + if (nextChildren === prevChildren) { + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes ); } - } - } - } // Cache unmasked context so we can avoid recreating masked context unless necessary. - // ReactFiberContext usually updates this cache but can't for newly-created instances. - - if (isLegacyContextConsumer) { - cacheContext(workInProgress, unmaskedContext, context); - } - - return instance; -} - -function callComponentWillMount(workInProgress, instance) { - var oldState = instance.state; - if (typeof instance.componentWillMount === "function") { - instance.componentWillMount(); - } - - if (typeof instance.UNSAFE_componentWillMount === "function") { - instance.UNSAFE_componentWillMount(); - } + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + } - if (oldState !== instance.state) { - { - error( - "%s.componentWillMount(): Assigning directly to this.state is " + - "deprecated (except inside a component's " + - "constructor). Use setState instead.", - getComponentNameFromFiber(workInProgress) || "Component" - ); + return workInProgress.child; } - classComponentUpdater.enqueueReplaceState(instance, instance.state, null); - } -} - -function callComponentWillReceiveProps( - workInProgress, - instance, - newProps, - nextContext -) { - var oldState = instance.state; + function updateHostComponent$1(current, workInProgress, renderLanes) { + pushHostContext(workInProgress); - if (typeof instance.componentWillReceiveProps === "function") { - instance.componentWillReceiveProps(newProps, nextContext); - } + var type = workInProgress.type; + var nextProps = workInProgress.pendingProps; + var prevProps = current !== null ? current.memoizedProps : null; + var nextChildren = nextProps.children; + var isDirectTextChild = shouldSetTextContent(type, nextProps); - if (typeof instance.UNSAFE_componentWillReceiveProps === "function") { - instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); - } + if (isDirectTextChild) { + // We special case a direct text child of a host node. This is a common + // case. We won't handle it as a reified child. We will instead handle + // this in the host environment that also has access to this prop. That + // avoids allocating another HostText fiber and traversing it. + nextChildren = null; + } else if (prevProps !== null && shouldSetTextContent(type, prevProps)) { + // If we're switching from a direct text child to a normal child, or to + // empty, we need to schedule the text content to be reset. + workInProgress.flags |= ContentReset; + } - if (instance.state !== oldState) { - { - var componentName = - getComponentNameFromFiber(workInProgress) || "Component"; + markRef$1(current, workInProgress); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } - if (!didWarnAboutStateAssignmentForComponent.has(componentName)) { - didWarnAboutStateAssignmentForComponent.add(componentName); + function updateHostText$1(current, workInProgress) { + // immediately after. - error( - "%s.componentWillReceiveProps(): Assigning directly to " + - "this.state is deprecated (except inside a component's " + - "constructor). Use setState instead.", - componentName - ); - } + return null; } - classComponentUpdater.enqueueReplaceState(instance, instance.state, null); - } -} // Invokes the mount life-cycles on a previously never rendered instance. - -function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { - { - checkClassInstance(workInProgress, ctor, newProps); - } + function mountLazyComponent( + _current, + workInProgress, + elementType, + renderLanes + ) { + resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); + var props = workInProgress.pendingProps; + var lazyComponent = elementType; + var payload = lazyComponent._payload; + var init = lazyComponent._init; + var Component = init(payload); // Store the unwrapped component in the type. + + workInProgress.type = Component; + var resolvedTag = (workInProgress.tag = + resolveLazyComponentTag(Component)); + var resolvedProps = resolveDefaultProps(Component, props); + var child; + + switch (resolvedTag) { + case FunctionComponent: { + { + validateFunctionComponentInDev(workInProgress, Component); + workInProgress.type = Component = + resolveFunctionForHotReloading(Component); + } - var instance = workInProgress.stateNode; - instance.props = newProps; - instance.state = workInProgress.memoizedState; - instance.refs = {}; - initializeUpdateQueue(workInProgress); - var contextType = ctor.contextType; + child = updateFunctionComponent( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; + } - if (typeof contextType === "object" && contextType !== null) { - instance.context = readContext(contextType); - } else { - var unmaskedContext = getUnmaskedContext(workInProgress, ctor, true); - instance.context = getMaskedContext(workInProgress, unmaskedContext); - } + case ClassComponent: { + { + workInProgress.type = Component = + resolveClassForHotReloading(Component); + } - { - if (instance.state === newProps) { - var componentName = getComponentNameFromType(ctor) || "Component"; + child = updateClassComponent( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; + } - if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) { - didWarnAboutDirectlyAssigningPropsToState.add(componentName); + case ForwardRef: { + { + workInProgress.type = Component = + resolveForwardRefForHotReloading(Component); + } - 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 - ); - } - } + child = updateForwardRef( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; + } - if (workInProgress.mode & StrictLegacyMode) { - ReactStrictModeWarnings.recordLegacyContextWarning( - workInProgress, - instance - ); - } + case MemoComponent: { + { + if (workInProgress.type !== workInProgress.elementType) { + var outerPropTypes = Component.propTypes; + + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + resolvedProps, // Resolved for outer only + "prop", + getComponentNameFromType(Component) + ); + } + } + } - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings( - workInProgress, - instance - ); - } + child = updateMemoComponent( + null, + workInProgress, + Component, + resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too + renderLanes + ); + return child; + } + } - instance.state = workInProgress.memoizedState; - var getDerivedStateFromProps = ctor.getDerivedStateFromProps; + var hint = ""; - if (typeof getDerivedStateFromProps === "function") { - applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - newProps - ); - instance.state = workInProgress.memoizedState; - } // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for components using the new APIs. - - if ( - typeof ctor.getDerivedStateFromProps !== "function" && - typeof instance.getSnapshotBeforeUpdate !== "function" && - (typeof instance.UNSAFE_componentWillMount === "function" || - typeof instance.componentWillMount === "function") - ) { - callComponentWillMount(workInProgress, instance); // If we had additional state updates during this life-cycle, let's - // process them now. - - processUpdateQueue(workInProgress, newProps, instance, renderLanes); - instance.state = workInProgress.memoizedState; - } - - if (typeof instance.componentDidMount === "function") { - workInProgress.flags |= Update | LayoutStatic; - } - - if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { - workInProgress.flags |= MountLayoutDev; - } -} + { + if ( + Component !== null && + typeof Component === "object" && + Component.$$typeof === REACT_LAZY_TYPE + ) { + hint = " Did you wrap a component in React.lazy() more than once?"; + } + } // This message intentionally doesn't mention ForwardRef or MemoComponent + // because the fact that it's a separate type of work is an + // implementation detail. -function resumeMountClassInstance(workInProgress, ctor, newProps, renderLanes) { - var instance = workInProgress.stateNode; - var oldProps = workInProgress.memoizedProps; - instance.props = oldProps; - var oldContext = instance.context; - var contextType = ctor.contextType; - var nextContext = emptyContextObject; - - if (typeof contextType === "object" && contextType !== null) { - nextContext = readContext(contextType); - } else { - var nextLegacyUnmaskedContext = getUnmaskedContext( - workInProgress, - ctor, - true - ); - nextContext = getMaskedContext(workInProgress, nextLegacyUnmaskedContext); - } - - var getDerivedStateFromProps = ctor.getDerivedStateFromProps; - var hasNewLifecycles = - typeof getDerivedStateFromProps === "function" || - typeof instance.getSnapshotBeforeUpdate === "function"; // Note: During these life-cycles, instance.props/instance.state are what - // ever the previously attempted to render - not the "current". However, - // during componentDidUpdate we pass the "current" props. - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for components using the new APIs. - - if ( - !hasNewLifecycles && - (typeof instance.UNSAFE_componentWillReceiveProps === "function" || - typeof instance.componentWillReceiveProps === "function") - ) { - if (oldProps !== newProps || oldContext !== nextContext) { - callComponentWillReceiveProps( - workInProgress, - instance, - newProps, - nextContext + 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) ); } - } - - resetHasForceUpdateBeforeProcessing(); - var oldState = workInProgress.memoizedState; - var newState = (instance.state = oldState); - processUpdateQueue(workInProgress, newProps, instance, renderLanes); - newState = workInProgress.memoizedState; - - if ( - oldProps === newProps && - oldState === newState && - !hasContextChanged() && - !checkHasForceUpdateAfterProcessing() - ) { - // If an update was already in progress, we should schedule an Update - // effect even though we're bailing out, so that cWU/cDU are called. - if (typeof instance.componentDidMount === "function") { - workInProgress.flags |= Update | LayoutStatic; - } - if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { - workInProgress.flags |= MountLayoutDev; - } - - return false; - } - - if (typeof getDerivedStateFromProps === "function") { - applyDerivedStateFromProps( + function mountIncompleteClassComponent( + _current, workInProgress, - ctor, - getDerivedStateFromProps, - newProps - ); - newState = workInProgress.memoizedState; - } + Component, + nextProps, + renderLanes + ) { + resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); // Promote the fiber to a class and try rendering again. - var shouldUpdate = - checkHasForceUpdateAfterProcessing() || - checkShouldComponentUpdate( - workInProgress, - ctor, - oldProps, - newProps, - oldState, - newState, - nextContext - ); + workInProgress.tag = ClassComponent; // The rest of this function is a fork of `updateClassComponent` + // Push context providers early to prevent context stack mismatches. + // During mounting we don't know the child context yet as the instance doesn't exist. + // We will invalidate the child context in finishClassComponent() right after rendering. - if (shouldUpdate) { - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for components using the new APIs. - if ( - !hasNewLifecycles && - (typeof instance.UNSAFE_componentWillMount === "function" || - typeof instance.componentWillMount === "function") - ) { - if (typeof instance.componentWillMount === "function") { - instance.componentWillMount(); - } + var hasContext; - if (typeof instance.UNSAFE_componentWillMount === "function") { - instance.UNSAFE_componentWillMount(); + if (isContextProvider(Component)) { + hasContext = true; + pushContextProvider(workInProgress); + } else { + hasContext = false; } - } - if (typeof instance.componentDidMount === "function") { - workInProgress.flags |= Update | LayoutStatic; - } - - if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { - workInProgress.flags |= MountLayoutDev; - } - } else { - // If an update was already in progress, we should schedule an Update - // effect even though we're bailing out, so that cWU/cDU are called. - if (typeof instance.componentDidMount === "function") { - workInProgress.flags |= Update | LayoutStatic; - } - - if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { - workInProgress.flags |= MountLayoutDev; - } // If shouldComponentUpdate returned false, we should still update the - // memoized state to indicate that this work can be reused. - - workInProgress.memoizedProps = newProps; - workInProgress.memoizedState = newState; - } // Update the existing instance's state, props, and context pointers even - // if shouldComponentUpdate returns false. - - instance.props = newProps; - instance.state = newState; - instance.context = nextContext; - return shouldUpdate; -} // Invokes the update life-cycles and returns false if it shouldn't rerender. - -function updateClassInstance( - current, - workInProgress, - ctor, - newProps, - renderLanes -) { - var instance = workInProgress.stateNode; - cloneUpdateQueue(current, workInProgress); - var unresolvedOldProps = workInProgress.memoizedProps; - var oldProps = - workInProgress.type === workInProgress.elementType - ? unresolvedOldProps - : resolveDefaultProps(workInProgress.type, unresolvedOldProps); - instance.props = oldProps; - var unresolvedNewProps = workInProgress.pendingProps; - var oldContext = instance.context; - var contextType = ctor.contextType; - var nextContext = emptyContextObject; - - if (typeof contextType === "object" && contextType !== null) { - nextContext = readContext(contextType); - } else { - var nextUnmaskedContext = getUnmaskedContext(workInProgress, ctor, true); - nextContext = getMaskedContext(workInProgress, nextUnmaskedContext); - } - - var getDerivedStateFromProps = ctor.getDerivedStateFromProps; - var hasNewLifecycles = - typeof getDerivedStateFromProps === "function" || - typeof instance.getSnapshotBeforeUpdate === "function"; // Note: During these life-cycles, instance.props/instance.state are what - // ever the previously attempted to render - not the "current". However, - // during componentDidUpdate we pass the "current" props. - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for components using the new APIs. - - if ( - !hasNewLifecycles && - (typeof instance.UNSAFE_componentWillReceiveProps === "function" || - typeof instance.componentWillReceiveProps === "function") - ) { - if ( - unresolvedOldProps !== unresolvedNewProps || - oldContext !== nextContext - ) { - callComponentWillReceiveProps( + prepareToReadContext(workInProgress, renderLanes); + constructClassInstance(workInProgress, Component, nextProps); + mountClassInstance(workInProgress, Component, nextProps, renderLanes); + return finishClassComponent( + null, workInProgress, - instance, - newProps, - nextContext + Component, + true, + hasContext, + renderLanes ); } - } - - resetHasForceUpdateBeforeProcessing(); - var oldState = workInProgress.memoizedState; - var newState = (instance.state = oldState); - processUpdateQueue(workInProgress, newProps, instance, renderLanes); - newState = workInProgress.memoizedState; - - if ( - unresolvedOldProps === unresolvedNewProps && - oldState === newState && - !hasContextChanged() && - !checkHasForceUpdateAfterProcessing() && - !( - enableLazyContextPropagation && - current !== null && - current.dependencies !== null && - checkIfContextChanged(current.dependencies) - ) - ) { - // If an update was already in progress, we should schedule an Update - // effect even though we're bailing out, so that cWU/cDU are called. - if (typeof instance.componentDidUpdate === "function") { - if ( - unresolvedOldProps !== current.memoizedProps || - oldState !== current.memoizedState - ) { - workInProgress.flags |= Update; - } - } - - if (typeof instance.getSnapshotBeforeUpdate === "function") { - if ( - unresolvedOldProps !== current.memoizedProps || - oldState !== current.memoizedState - ) { - workInProgress.flags |= Snapshot; - } - } - - return false; - } - - if (typeof getDerivedStateFromProps === "function") { - applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - newProps - ); - newState = workInProgress.memoizedState; - } - var shouldUpdate = - checkHasForceUpdateAfterProcessing() || - checkShouldComponentUpdate( + function mountIndeterminateComponent( + _current, workInProgress, - ctor, - oldProps, - newProps, - oldState, - newState, - nextContext - ) || // TODO: In some cases, we'll end up checking if context has changed twice, - // both before and after `shouldComponentUpdate` has been called. Not ideal, - // but I'm loath to refactor this function. This only happens for memoized - // components so it's not that common. - (enableLazyContextPropagation && - current !== null && - current.dependencies !== null && - checkIfContextChanged(current.dependencies)); - - if (shouldUpdate) { - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for components using the new APIs. - if ( - !hasNewLifecycles && - (typeof instance.UNSAFE_componentWillUpdate === "function" || - typeof instance.componentWillUpdate === "function") + Component, + renderLanes ) { - if (typeof instance.componentWillUpdate === "function") { - instance.componentWillUpdate(newProps, newState, nextContext); - } + resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); + var props = workInProgress.pendingProps; + var context; - if (typeof instance.UNSAFE_componentWillUpdate === "function") { - instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext); + { + var unmaskedContext = getUnmaskedContext( + workInProgress, + Component, + false + ); + context = getMaskedContext(workInProgress, unmaskedContext); } - } - - if (typeof instance.componentDidUpdate === "function") { - workInProgress.flags |= Update; - } - if (typeof instance.getSnapshotBeforeUpdate === "function") { - workInProgress.flags |= Snapshot; - } - } else { - // If an update was already in progress, we should schedule an Update - // effect even though we're bailing out, so that cWU/cDU are called. - if (typeof instance.componentDidUpdate === "function") { - if ( - unresolvedOldProps !== current.memoizedProps || - oldState !== current.memoizedState - ) { - workInProgress.flags |= Update; - } - } + prepareToReadContext(workInProgress, renderLanes); + var value; - if (typeof instance.getSnapshotBeforeUpdate === "function") { - if ( - unresolvedOldProps !== current.memoizedProps || - oldState !== current.memoizedState - ) { - workInProgress.flags |= Snapshot; + if (enableSchedulingProfiler) { + markComponentRenderStarted(workInProgress); } - } // If shouldComponentUpdate returned false, we should still update the - // memoized props/state to indicate that this work can be reused. - workInProgress.memoizedProps = newProps; - workInProgress.memoizedState = newState; - } // Update the existing instance's state, props, and context pointers even - // if shouldComponentUpdate returns false. - - instance.props = newProps; - instance.state = newState; - instance.context = nextContext; - return shouldUpdate; -} + { + if ( + Component.prototype && + typeof Component.prototype.render === "function" + ) { + var componentName = getComponentNameFromType(Component) || "Unknown"; -function createCapturedValueAtFiber(value, source) { - // If the value is an error, call this function immediately after it is thrown - // so the stack is accurate. - return { - value: value, - source: source, - stack: getStackByFiberInDevAndProd(source), - digest: null - }; -} -function createCapturedValue(value, digest, stack) { - return { - value: value, - source: null, - stack: stack != null ? stack : null, - digest: digest != null ? digest : null - }; -} + if (!didWarnAboutBadClass[componentName]) { + 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 + ); -var ReactFiberErrorDialogWWW = require("ReactFiberErrorDialog"); + didWarnAboutBadClass[componentName] = true; + } + } -if (typeof ReactFiberErrorDialogWWW.showErrorDialog !== "function") { - throw new Error( - "Expected ReactFiberErrorDialog.showErrorDialog to be a function." - ); -} + if (workInProgress.mode & StrictLegacyMode) { + ReactStrictModeWarnings.recordLegacyContextWarning( + workInProgress, + null + ); + } -function showErrorDialog(boundary, errorInfo) { - var capturedError = { - componentStack: errorInfo.stack !== null ? errorInfo.stack : "", - error: errorInfo.value, - errorBoundary: - boundary !== null && boundary.tag === ClassComponent - ? boundary.stateNode - : null - }; - return ReactFiberErrorDialogWWW.showErrorDialog(capturedError); -} + setIsRendering(true); + ReactCurrentOwner$1.current = workInProgress; + value = renderWithHooks( + null, + workInProgress, + Component, + props, + context, + renderLanes + ); + setIsRendering(false); + } -function logCapturedError(boundary, errorInfo) { - try { - var logError = showErrorDialog(boundary, errorInfo); // Allow injected showErrorDialog() to prevent default console.error logging. - // This enables renderers like ReactNative to better manage redbox behavior. + if (enableSchedulingProfiler) { + markComponentRenderStopped(); + } // React DevTools reads this flag. - if (logError === false) { - return; - } + workInProgress.flags |= PerformedWork; - var error = errorInfo.value; + { + // Support for module components is deprecated and is removed behind a flag. + // Whether or not it would crash later, we want to show a good message in DEV first. + if ( + typeof value === "object" && + value !== null && + typeof value.render === "function" && + value.$$typeof === undefined + ) { + var _componentName = getComponentNameFromType(Component) || "Unknown"; - if (true) { - var source = errorInfo.source; - var stack = errorInfo.stack; - var componentStack = stack !== null ? stack : ""; // Browsers support silencing uncaught errors by calling - // `preventDefault()` in window `error` handler. - // We record this information as an expando on the error. + if (!didWarnAboutModulePatternComponent[_componentName]) { + 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 + ); - if (error != null && error._suppressLogging) { - if (boundary.tag === ClassComponent) { - // The error is recoverable and was silenced. - // Ignore it and don't print the stack addendum. - // This is handy for testing error boundaries without noise. - return; - } // The error is fatal. Since the silencing might have - // been accidental, we'll surface it anyway. - // However, the browser would have silenced the original error - // so we'll print it first, and then print the stack addendum. - - console["error"](error); // Don't transform to our wrapper - // For a more detailed description of this block, see: - // https://github.com/facebook/react/pull/13384 - } - - var componentName = source ? getComponentNameFromFiber(source) : null; - var componentNameMessage = componentName - ? "The above error occurred in the <" + componentName + "> component:" - : "The above error occurred in one of your React components:"; - var errorBoundaryMessage; - - if (boundary.tag === HostRoot) { - 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."; - } else { - var errorBoundaryName = - getComponentNameFromFiber(boundary) || "Anonymous"; - errorBoundaryMessage = - "React will try to recreate this component tree from scratch " + - ("using the error boundary you provided, " + errorBoundaryName + "."); - } - - var combinedMessage = - componentNameMessage + - "\n" + - componentStack + - "\n\n" + - ("" + errorBoundaryMessage); // In development, we provide our own message with just the component stack. - // We don't include the original error message and JS stack because the browser - // has already printed it. Even if the application swallows the error, it is still - // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils. - - console["error"](combinedMessage); // Don't transform to our wrapper - } - } catch (e) { - // This method must not throw, or React internal state will get messed up. - // If console.error is overridden, or logCapturedError() shows a dialog that throws, - // we want to report this error outside of the normal stack as a last resort. - // https://github.com/facebook/react/issues/13188 - setTimeout(function () { - throw e; - }); - } -} + didWarnAboutModulePatternComponent[_componentName] = true; + } + } + } -function createRootErrorUpdate(fiber, errorInfo, lane) { - var update = createUpdate(lane); // Unmount the root by rendering null. + { + // Proceed under the assumption that this is a function component + workInProgress.tag = FunctionComponent; - update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property - // being called "element". + reconcileChildren(null, workInProgress, value, renderLanes); - update.payload = { - element: null - }; - var error = errorInfo.value; + { + validateFunctionComponentInDev(workInProgress, Component); + } - update.callback = function () { - onUncaughtError(error); - logCapturedError(fiber, errorInfo); - }; + return workInProgress.child; + } + } - return update; -} + function validateFunctionComponentInDev(workInProgress, Component) { + { + if (Component) { + if (Component.childContextTypes) { + error( + "%s(...): childContextTypes cannot be defined on a function component.", + Component.displayName || Component.name || "Component" + ); + } + } -function createClassErrorUpdate(fiber, errorInfo, lane) { - var update = createUpdate(lane); - update.tag = CaptureUpdate; - var getDerivedStateFromError = fiber.type.getDerivedStateFromError; + if (workInProgress.ref !== null) { + var info = ""; + var ownerName = getCurrentFiberOwnerNameInDevOrNull(); - if (typeof getDerivedStateFromError === "function") { - var error$1 = errorInfo.value; + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; + } - update.payload = function () { - return getDerivedStateFromError(error$1); - }; + var warningKey = ownerName || ""; + var debugSource = workInProgress._debugSource; - update.callback = function () { - { - markFailedErrorBoundaryForHotReloading(fiber); - } + if (debugSource) { + warningKey = debugSource.fileName + ":" + debugSource.lineNumber; + } - logCapturedError(fiber, errorInfo); - }; - } + if (!didWarnAboutFunctionRefs[warningKey]) { + didWarnAboutFunctionRefs[warningKey] = true; - var inst = fiber.stateNode; + error( + "Function components cannot be given refs. " + + "Attempts to access this ref will fail. " + + "Did you mean to use React.forwardRef()?%s", + info + ); + } + } - if (inst !== null && typeof inst.componentDidCatch === "function") { - // $FlowFixMe[missing-this-annot] - update.callback = function callback() { - { - markFailedErrorBoundaryForHotReloading(fiber); - } + if (Component.defaultProps !== undefined) { + var componentName = getComponentNameFromType(Component) || "Unknown"; - logCapturedError(fiber, errorInfo); + if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) { + error( + "%s: Support for defaultProps will be removed from function components " + + "in a future major release. Use JavaScript default parameters instead.", + componentName + ); - if (typeof getDerivedStateFromError !== "function") { - // To preserve the preexisting retry behavior of error boundaries, - // we keep track of which ones already failed during this batch. - // This gets reset before we yield back to the browser. - // TODO: Warn in strict mode if getDerivedStateFromError is - // not defined. - markLegacyErrorBoundaryAsFailed(this); - } + didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true; + } + } - var error$1 = errorInfo.value; - var stack = errorInfo.stack; - this.componentDidCatch(error$1, { - componentStack: stack !== null ? stack : "" - }); + if (typeof Component.getDerivedStateFromProps === "function") { + var _componentName3 = + getComponentNameFromType(Component) || "Unknown"; - { - if (typeof getDerivedStateFromError !== "function") { - // If componentDidCatch is the only error boundary method defined, - // then it needs to call setState to recover from errors. - // If no state update is scheduled then the boundary will swallow the error. - if (!includesSomeLane(fiber.lanes, SyncLane)) { + if ( + !didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] + ) { 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" + "%s: Function components do not support getDerivedStateFromProps.", + _componentName3 ); + + didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = + true; } } - } - }; - } - return update; -} + if ( + typeof Component.contextType === "object" && + Component.contextType !== null + ) { + var _componentName4 = + getComponentNameFromType(Component) || "Unknown"; -function resetSuspendedComponent(sourceFiber, rootRenderLanes) { - if (enableLazyContextPropagation) { - var currentSourceFiber = sourceFiber.alternate; + if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { + error( + "%s: Function components do not support contextType.", + _componentName4 + ); - if (currentSourceFiber !== null) { - // Since we never visited the children of the suspended component, we - // need to propagate the context change now, to ensure that we visit - // them during the retry. - // - // We don't have to do this for errors because we retry errors without - // committing in between. So this is specific to Suspense. - propagateParentContextChangesToDeferredTree( - currentSourceFiber, - sourceFiber, - rootRenderLanes - ); + didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; + } + } + } } - } // Reset the memoizedState to what it was before we attempted to render it. - // A legacy mode Suspense quirk, only relevant to hook components. - var tag = sourceFiber.tag; - - if ( - (sourceFiber.mode & ConcurrentMode) === NoMode && - (tag === FunctionComponent || - tag === ForwardRef || - tag === SimpleMemoComponent) - ) { - var currentSource = sourceFiber.alternate; + var SUSPENDED_MARKER = { + dehydrated: null, + treeContext: null, + retryLane: NoLane + }; - if (currentSource) { - sourceFiber.updateQueue = currentSource.updateQueue; - sourceFiber.memoizedState = currentSource.memoizedState; - sourceFiber.lanes = currentSource.lanes; - } else { - sourceFiber.updateQueue = null; - sourceFiber.memoizedState = null; + function mountSuspenseOffscreenState(renderLanes) { + return { + baseLanes: renderLanes, + cachePool: getSuspendedCache() + }; } - } -} -function markSuspenseBoundaryShouldCapture( - suspenseBoundary, - returnFiber, - sourceFiber, - root, - rootRenderLanes -) { - // This marks a Suspense boundary so that when we're unwinding the stack, - // it captures the suspended "exception" and does a second (fallback) pass. - if ((suspenseBoundary.mode & ConcurrentMode) === NoMode) { - // Legacy Mode Suspense - // - // If the boundary is in legacy mode, we should *not* - // suspend the commit. Pretend as if the suspended component rendered - // null and keep rendering. When the Suspense boundary completes, - // we'll do a second pass to render the fallback. - if (suspenseBoundary === returnFiber) { - // Special case where we suspended while reconciling the children of - // a Suspense boundary's inner Offscreen wrapper fiber. This happens - // when a React.lazy component is a direct child of a - // Suspense boundary. - // - // Suspense boundaries are implemented as multiple fibers, but they - // are a single conceptual unit. The legacy mode behavior where we - // pretend the suspended fiber committed as `null` won't work, - // because in this case the "suspended" fiber is the inner - // Offscreen wrapper. - // - // Because the contents of the boundary haven't started rendering - // yet (i.e. nothing in the tree has partially rendered) we can - // switch to the regular, concurrent mode behavior: mark the - // boundary with ShouldCapture and enter the unwind phase. - suspenseBoundary.flags |= ShouldCapture; - } else { - suspenseBoundary.flags |= DidCapture; - sourceFiber.flags |= ForceUpdateForLegacySuspense; // We're going to commit this fiber even though it didn't complete. - // But we shouldn't call any lifecycle methods or callbacks. Remove - // all lifecycle effect tags. + function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { + var cachePool = null; - sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete); + { + var prevCachePool = prevOffscreenState.cachePool; - if (sourceFiber.tag === ClassComponent) { - var currentSourceFiber = sourceFiber.alternate; + if (prevCachePool !== null) { + var parentCache = CacheContext._currentValue2; - if (currentSourceFiber === null) { - // This is a new mount. Change the tag so it's not mistaken for a - // completed class component. For example, we should not call - // componentWillUnmount if it is deleted. - sourceFiber.tag = IncompleteClassComponent; + if (prevCachePool.parent !== parentCache) { + // Detected a refresh in the parent. This overrides any previously + // suspended cache. + cachePool = { + parent: parentCache, + pool: parentCache + }; + } else { + // We can reuse the cache from last time. The only thing that would have + // overridden it is a parent refresh, which we checked for above. + cachePool = prevCachePool; + } } else { - // When we try rendering again, we should not reuse the current fiber, - // since it's known to be in an inconsistent state. Use a force update to - // prevent a bail out. - var update = createUpdate(SyncLane); - update.tag = ForceUpdate; - enqueueUpdate(sourceFiber, update, SyncLane); - } - } // The source fiber did not complete. Mark it with Sync priority to - // indicate that it still has pending work. - - sourceFiber.lanes = mergeLanes(sourceFiber.lanes, SyncLane); - } - - return suspenseBoundary; - } // Confirmed that the boundary is in a concurrent mode tree. Continue - // with the normal suspend path. - // - // After this we'll use a set of heuristics to determine whether this - // render pass will run to completion or restart or "suspend" the commit. - // The actual logic for this is spread out in different places. - // - // This first principle is that if we're going to suspend when we complete - // a root, then we should also restart if we get an update or ping that - // might unsuspend it, and vice versa. The only reason to suspend is - // because you think you might want to restart before committing. However, - // it doesn't make sense to restart only while in the period we're suspended. - // - // Restarting too aggressively is also not good because it starves out any - // intermediate loading state. So we use heuristics to determine when. - // Suspense Heuristics - // - // If nothing threw a Promise or all the same fallbacks are already showing, - // then don't suspend/restart. - // - // If this is an initial render of a new tree of Suspense boundaries and - // those trigger a fallback, then don't suspend/restart. We want to ensure - // that we can show the initial loading state as quickly as possible. - // - // If we hit a "Delayed" case, such as when we'd switch from content back into - // a fallback, then we should always suspend/restart. Transitions apply - // to this case. If none is defined, JND is used instead. - // - // If we're already showing a fallback and it gets "retried", allowing us to show - // another level, but there's still an inner boundary that would show a fallback, - // then we suspend/restart for 500ms since the last time we showed a fallback - // anywhere in the tree. This effectively throttles progressive loading into a - // consistent train of commits. This also gives us an opportunity to restart to - // get to the completed state slightly earlier. - // - // If there's ambiguity due to batching it's resolved in preference of: - // 1) "delayed", 2) "initial render", 3) "retry". - // - // We want to ensure that a "busy" state doesn't get force committed. We want to - // ensure that new initial loading states can commit as soon as possible. - - suspenseBoundary.flags |= ShouldCapture; // TODO: I think we can remove this, since we now use `DidCapture` in - // the begin phase to prevent an early bailout. - - suspenseBoundary.lanes = rootRenderLanes; - return suspenseBoundary; -} + // If there's no previous cache pool, grab the current one. + cachePool = getSuspendedCache(); + } + } + + return { + baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), + cachePool: cachePool + }; + } // TODO: Probably should inline this back + + function shouldRemainOnFallback(current, workInProgress, renderLanes) { + // If we're already showing a fallback, there are cases where we need to + // remain on that fallback regardless of whether the content has resolved. + // For example, SuspenseList coordinates when nested content appears. + // TODO: For compatibility with offscreen prerendering, this should also check + // whether the current fiber (if it exists) was visible in the previous tree. + if (current !== null) { + var suspenseState = current.memoizedState; + + if (suspenseState === null) { + // Currently showing content. Don't hide it, even if ForceSuspenseFallback + // is true. More precise name might be "ForceRemainSuspenseFallback". + // Note: This is a factoring smell. Can't remain on a fallback if there's + // no fallback to remain on. + return false; + } + } // Not currently showing content. Consult the Suspense context. -function throwException( - root, - returnFiber, - sourceFiber, - value, - rootRenderLanes -) { - // The source fiber did not complete. - sourceFiber.flags |= Incomplete; + var suspenseContext = suspenseStackCursor.current; + return hasSuspenseListContext(suspenseContext, ForceSuspenseFallback); + } - { - if (isDevToolsPresent) { - // If we have pending work still, restore the original updaters - restorePendingUpdaters(root, rootRenderLanes); + function getRemainingWorkInPrimaryTree(current, renderLanes) { + // TODO: Should not remove render lanes that were pinged during this render + return removeLanes(current.childLanes, renderLanes); } - } - if (value !== null && typeof value === "object") { - if (typeof value.then === "function") { - // This is a wakeable. The component suspended. - var wakeable = value; - resetSuspendedComponent(sourceFiber, rootRenderLanes); + function updateSuspenseComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend. { - if (enableDebugTracing) { - if (sourceFiber.mode & DebugTracingMode) { - var name = getComponentNameFromFiber(sourceFiber) || "Unknown"; - logComponentSuspended(name, wakeable); - } - } - } // Mark the nearest Suspense boundary to switch to rendering a fallback. - - var suspenseBoundary = getSuspenseHandler(); - - if (suspenseBoundary !== null) { - switch (suspenseBoundary.tag) { - case SuspenseComponent: { - // If this suspense boundary is not already showing a fallback, mark - // the in-progress render as suspended. We try to perform this logic - // as soon as soon as possible during the render phase, so the work - // loop can know things like whether it's OK to switch to other tasks, - // or whether it can wait for data to resolve before continuing. - // TODO: Most of these checks are already performed when entering a - // Suspense boundary. We should track the information on the stack so - // we don't have to recompute it on demand. This would also allow us - // to unify with `use` which needs to perform this logic even sooner, - // before `throwException` is called. - if (sourceFiber.mode & ConcurrentMode) { - if (getShellBoundary() === null) { - // Suspended in the "shell" of the app. This is an undesirable - // loading state. We should avoid committing this tree. - renderDidSuspendDelayIfPossible(); - } else { - // If we suspended deeper than the shell, we don't need to delay - // the commmit. However, we still call renderDidSuspend if this is - // a new boundary, to tell the work loop that a new fallback has - // appeared during this render. - // TODO: Theoretically we should be able to delete this branch. - // It's currently used for two things: 1) to throttle the - // appearance of successive loading states, and 2) in - // SuspenseList, to determine whether the children include any - // pending fallbacks. For 1, we should apply throttling to all - // retries, not just ones that render an additional fallback. For - // 2, we should check subtreeFlags instead. Then we can delete - // this branch. - var current = suspenseBoundary.alternate; - - if (current === null) { - renderDidSuspend(); - } - } - } + if (shouldSuspend(workInProgress)) { + workInProgress.flags |= DidCapture; + } + } - suspenseBoundary.flags &= ~ForceClientRender; - markSuspenseBoundaryShouldCapture( - suspenseBoundary, - returnFiber, - sourceFiber, - root, - rootRenderLanes - ); // Retry listener - // - // If the fallback does commit, we need to attach a different type of - // listener. This one schedules an update on the Suspense boundary to - // turn the fallback state off. - // - // Stash the wakeable on the boundary fiber so we can access it in the - // commit phase. - // - // When the wakeable resolves, we'll attempt to render the boundary - // again ("retry"). - // Check if this is a Suspensey resource. We do not attach retry - // listeners to these, because we don't actually need them for - // rendering. Only for committing. Instead, if a fallback commits - // and the only thing that suspended was a Suspensey resource, we - // retry immediately. - // TODO: Refactor throwException so that we don't have to do this type - // check. The caller already knows what the cause was. - - var isSuspenseyResource = wakeable === noopSuspenseyCommitThenable; - - if (isSuspenseyResource) { - suspenseBoundary.flags |= ScheduleRetry; - } else { - var retryQueue = suspenseBoundary.updateQueue; + var showFallback = false; + var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags$1; - if (retryQueue === null) { - suspenseBoundary.updateQueue = new Set([wakeable]); + if (didSuspend || shouldRemainOnFallback(current)) { + // Something in this boundary's subtree already suspended. Switch to + // rendering the fallback children. + showFallback = true; + workInProgress.flags &= ~DidCapture; + } // OK, the next part is confusing. We're about to reconcile the Suspense + // boundary's children. This involves some custom reconciliation logic. Two + // main reasons this is so complicated. + // + // First, Legacy Mode has different semantics for backwards compatibility. The + // primary tree will commit in an inconsistent state, so when we do the + // second pass to render the fallback, we do some exceedingly, uh, clever + // hacks to make that not totally break. Like transferring effects and + // deletions from hidden tree. In Concurrent Mode, it's much simpler, + // because we bailout on the primary tree completely and leave it in its old + // state, no effects. Same as what we do for Offscreen (except that + // Offscreen doesn't have the first render pass). + // + // Second is hydration. During hydration, the Suspense fiber has a slightly + // different layout, where the child points to a dehydrated fragment, which + // contains the DOM rendered by the server. + // + // Third, even if you set all that aside, Suspense is like error boundaries in + // that we first we try to render one tree, and if that fails, we render again + // and switch to a different tree. Like a try/catch block. So we have to track + // which branch we're currently rendering. Ideally we would model this using + // a stack. + + if (current === null) { + var nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; + + if (showFallback) { + pushFallbackTreeSuspenseHandler(workInProgress); + var fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); + var primaryChildFragment = workInProgress.child; + primaryChildFragment.memoizedState = + mountSuspenseOffscreenState(renderLanes); + workInProgress.memoizedState = SUSPENDED_MARKER; + + if (enableTransitionTracing) { + var currentTransitions = getPendingTransitions(); + + if (currentTransitions !== null) { + var parentMarkerInstances = getMarkerInstances(); + var offscreenQueue = primaryChildFragment.updateQueue; + + if (offscreenQueue === null) { + var newOffscreenQueue = { + transitions: currentTransitions, + markerInstances: parentMarkerInstances, + retryQueue: null + }; + primaryChildFragment.updateQueue = newOffscreenQueue; } else { - retryQueue.add(wakeable); - } // We only attach ping listeners in concurrent mode. Legacy - // Suspense always commits fallbacks synchronously, so there are - // no pings. - - if (suspenseBoundary.mode & ConcurrentMode) { - attachPingListener(root, wakeable, rootRenderLanes); + offscreenQueue.transitions = currentTransitions; + offscreenQueue.markerInstances = parentMarkerInstances; } } - - return; } - case OffscreenComponent: { - if (suspenseBoundary.mode & ConcurrentMode) { - suspenseBoundary.flags |= ShouldCapture; + return fallbackFragment; + } else if (typeof nextProps.unstable_expectedLoadTime === "number") { + // This is a CPU-bound tree. Skip this tree and show a placeholder to + // unblock the surrounding content. Then immediately retry after the + // initial commit. + pushFallbackTreeSuspenseHandler(workInProgress); - var _isSuspenseyResource = - wakeable === noopSuspenseyCommitThenable; + var _fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); - if (_isSuspenseyResource) { - suspenseBoundary.flags |= ScheduleRetry; - } else { - var offscreenQueue = suspenseBoundary.updateQueue; - - if (offscreenQueue === null) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - retryQueue: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var _retryQueue = offscreenQueue.retryQueue; + var _primaryChildFragment = workInProgress.child; + _primaryChildFragment.memoizedState = + mountSuspenseOffscreenState(renderLanes); + workInProgress.memoizedState = SUSPENDED_MARKER; // TODO: Transition Tracing is not yet implemented for CPU Suspense. + // Since nothing actually suspended, there will nothing to ping this to + // get it started back up to attempt the next item. While in terms of + // priority this work has the same priority as this current render, it's + // not part of the same transition once the transition has committed. If + // it's sync, we still want to yield so that it can be painted. + // Conceptually, this is really the same as pinging. We can use any + // RetryLane even if it's the one currently rendering since we're leaving + // it behind on this node. + + workInProgress.lanes = SomeRetryLane; + return _fallbackFragment; + } else { + pushPrimaryTreeSuspenseHandler(workInProgress); + return mountSuspensePrimaryChildren( + workInProgress, + nextPrimaryChildren + ); + } + } else { + // This is an update. + // Special path for hydration + var prevState = current.memoizedState; - if (_retryQueue === null) { - offscreenQueue.retryQueue = new Set([wakeable]); - } else { - _retryQueue.add(wakeable); - } - } + if (prevState !== null) { + var _dehydrated = prevState.dehydrated; + + if (_dehydrated !== null) { + return updateDehydratedSuspenseComponent( + current, + workInProgress, + didSuspend, + nextProps, + _dehydrated, + prevState, + renderLanes + ); + } + } - attachPingListener(root, wakeable, rootRenderLanes); + if (showFallback) { + pushFallbackTreeSuspenseHandler(workInProgress); + var _nextFallbackChildren = nextProps.fallback; + var _nextPrimaryChildren = nextProps.children; + var fallbackChildFragment = updateSuspenseFallbackChildren( + current, + workInProgress, + _nextPrimaryChildren, + _nextFallbackChildren, + renderLanes + ); + var _primaryChildFragment2 = workInProgress.child; + var prevOffscreenState = current.child.memoizedState; + _primaryChildFragment2.memoizedState = + prevOffscreenState === null + ? mountSuspenseOffscreenState(renderLanes) + : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); + + if (enableTransitionTracing) { + var _currentTransitions = getPendingTransitions(); + + if (_currentTransitions !== null) { + var _parentMarkerInstances = getMarkerInstances(); + + var _offscreenQueue = _primaryChildFragment2.updateQueue; + var currentOffscreenQueue = current.updateQueue; + + if (_offscreenQueue === null) { + var _newOffscreenQueue = { + transitions: _currentTransitions, + markerInstances: _parentMarkerInstances, + retryQueue: null + }; + _primaryChildFragment2.updateQueue = _newOffscreenQueue; + } else if (_offscreenQueue === currentOffscreenQueue) { + // If the work-in-progress queue is the same object as current, we + // can't modify it without cloning it first. + var _newOffscreenQueue2 = { + transitions: _currentTransitions, + markerInstances: _parentMarkerInstances, + retryQueue: + currentOffscreenQueue !== null + ? currentOffscreenQueue.retryQueue + : null + }; + _primaryChildFragment2.updateQueue = _newOffscreenQueue2; + } else { + _offscreenQueue.transitions = _currentTransitions; + _offscreenQueue.markerInstances = _parentMarkerInstances; } - - return; } } - } - throw new Error( - "Unexpected Suspense handler tag (" + - suspenseBoundary.tag + - "). This " + - "is a bug in React." - ); - } else { - // No boundary was found. Unless this is a sync update, this is OK. - // We can suspend and wait for more data to arrive. - if (root.tag === ConcurrentRoot) { - // In a concurrent root, suspending without a Suspense boundary is - // allowed. It will suspend indefinitely without committing. - // - // TODO: Should we have different behavior for discrete updates? What - // about flushSync? Maybe it should put the tree into an inert state, - // and potentially log a warning. Revisit this for a future release. - attachPingListener(root, wakeable, rootRenderLanes); - renderDidSuspendDelayIfPossible(); - return; + _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree( + current, + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + return fallbackChildFragment; } else { - // In a legacy root, suspending without a boundary is always an error. - 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." + pushPrimaryTreeSuspenseHandler(workInProgress); + var _nextPrimaryChildren2 = nextProps.children; + + var _primaryChildFragment3 = updateSuspensePrimaryChildren( + current, + workInProgress, + _nextPrimaryChildren2, + renderLanes ); - value = uncaughtSuspenseError; + + workInProgress.memoizedState = null; + return _primaryChildFragment3; } } } - } // This is a regular error, not a Suspense wakeable. - value = createCapturedValueAtFiber(value, sourceFiber); - renderDidError(value); // We didn't find a boundary that could handle this type of exception. Start - // over and traverse parent path again, this time treating the exception - // as an error. + function mountSuspensePrimaryChildren( + workInProgress, + primaryChildren, + renderLanes + ) { + var mode = workInProgress.mode; + var primaryChildProps = { + mode: "visible", + children: primaryChildren + }; + var primaryChildFragment = mountWorkInProgressOffscreenFiber( + primaryChildProps, + mode + ); + primaryChildFragment.return = workInProgress; + workInProgress.child = primaryChildFragment; + return primaryChildFragment; + } - var workInProgress = returnFiber; + function mountSuspenseFallbackChildren( + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes + ) { + var mode = workInProgress.mode; + var progressedPrimaryFragment = workInProgress.child; + var primaryChildProps = { + mode: "hidden", + children: primaryChildren + }; + var primaryChildFragment; + var fallbackChildFragment; - do { - switch (workInProgress.tag) { - case HostRoot: { - var _errorInfo = value; - workInProgress.flags |= ShouldCapture; - var lane = pickArbitraryLane(rootRenderLanes); - workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); - var update = createRootErrorUpdate(workInProgress, _errorInfo, lane); - enqueueCapturedUpdate(workInProgress, update); - return; + if ( + (mode & ConcurrentMode) === NoMode && + progressedPrimaryFragment !== null + ) { + // In legacy mode, we commit the primary tree as if it successfully + // completed, even though it's in an inconsistent state. + primaryChildFragment = progressedPrimaryFragment; + primaryChildFragment.childLanes = NoLanes; + primaryChildFragment.pendingProps = primaryChildProps; + + if (workInProgress.mode & ProfileMode) { + // Reset the durations from the first pass so they aren't included in the + // final amounts. This seems counterintuitive, since we're intentionally + // not measuring part of the render phase, but this makes it match what we + // do in Concurrent Mode. + primaryChildFragment.actualDuration = 0; + primaryChildFragment.actualStartTime = -1; + primaryChildFragment.selfBaseDuration = 0; + primaryChildFragment.treeBaseDuration = 0; + } + + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + } else { + primaryChildFragment = mountWorkInProgressOffscreenFiber( + primaryChildProps, + mode + ); + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); } - case ClassComponent: - // Capture and retry - var errorInfo = value; - var ctor = workInProgress.type; - var instance = workInProgress.stateNode; - - if ( - (workInProgress.flags & DidCapture) === NoFlags$1 && - (typeof ctor.getDerivedStateFromError === "function" || - (instance !== null && - typeof instance.componentDidCatch === "function" && - !isAlreadyFailedLegacyErrorBoundary(instance))) - ) { - workInProgress.flags |= ShouldCapture; - - var _lane = pickArbitraryLane(rootRenderLanes); + primaryChildFragment.return = workInProgress; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; + } - workInProgress.lanes = mergeLanes(workInProgress.lanes, _lane); // Schedule the error boundary to re-render using updated state + function mountWorkInProgressOffscreenFiber( + offscreenProps, + mode, + renderLanes + ) { + // The props argument to `createFiberFromOffscreen` is `any` typed, so we use + // this wrapper function to constrain it. + return createFiberFromOffscreen(offscreenProps, mode, NoLanes, null); + } - var _update = createClassErrorUpdate( - workInProgress, - errorInfo, - _lane - ); + function updateWorkInProgressOffscreenFiber(current, offscreenProps) { + // The props argument to `createWorkInProgress` is `any` typed, so we use this + // wrapper function to constrain it. + return createWorkInProgress(current, offscreenProps); + } - enqueueCapturedUpdate(workInProgress, _update); - return; + function updateSuspensePrimaryChildren( + current, + workInProgress, + primaryChildren, + renderLanes + ) { + var currentPrimaryChildFragment = current.child; + var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; + var primaryChildFragment = updateWorkInProgressOffscreenFiber( + currentPrimaryChildFragment, + { + mode: "visible", + children: primaryChildren } + ); - break; - } // $FlowFixMe[incompatible-type] we bail out when we get a null - - workInProgress = workInProgress.return; - } while (workInProgress !== null); -} - -var TransitionRoot = 0; -var TransitionTracingMarker = 1; -function processTransitionCallbacks(pendingTransitions, endTime, callbacks) { - if (enableTransitionTracing) { - if (pendingTransitions !== null) { - var transitionStart = pendingTransitions.transitionStart; - var onTransitionStart = callbacks.onTransitionStart; - - if (transitionStart !== null && onTransitionStart != null) { - transitionStart.forEach(function (transition) { - return onTransitionStart(transition.name, transition.startTime); - }); + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + primaryChildFragment.lanes = renderLanes; } - var markerProgress = pendingTransitions.markerProgress; - var onMarkerProgress = callbacks.onMarkerProgress; - - if (onMarkerProgress != null && markerProgress !== null) { - markerProgress.forEach(function (markerInstance, markerName) { - if (markerInstance.transitions !== null) { - // TODO: Clone the suspense object so users can't modify it - var pending = - markerInstance.pendingBoundaries !== null - ? Array.from(markerInstance.pendingBoundaries.values()) - : []; - markerInstance.transitions.forEach(function (transition) { - onMarkerProgress( - transition.name, - markerName, - transition.startTime, - endTime, - pending - ); - }); - } - }); - } + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = null; - var markerComplete = pendingTransitions.markerComplete; - var onMarkerComplete = callbacks.onMarkerComplete; + if (currentFallbackChildFragment !== null) { + // Delete the fallback child fragment + var deletions = workInProgress.deletions; - if (markerComplete !== null && onMarkerComplete != null) { - markerComplete.forEach(function (transitions, markerName) { - transitions.forEach(function (transition) { - onMarkerComplete( - transition.name, - markerName, - transition.startTime, - endTime - ); - }); - }); + if (deletions === null) { + workInProgress.deletions = [currentFallbackChildFragment]; + workInProgress.flags |= ChildDeletion; + } else { + deletions.push(currentFallbackChildFragment); + } } - var markerIncomplete = pendingTransitions.markerIncomplete; - var onMarkerIncomplete = callbacks.onMarkerIncomplete; + workInProgress.child = primaryChildFragment; + return primaryChildFragment; + } - if (onMarkerIncomplete != null && markerIncomplete !== null) { - markerIncomplete.forEach(function (_ref, markerName) { - var transitions = _ref.transitions, - aborts = _ref.aborts; - transitions.forEach(function (transition) { - var filteredAborts = []; - aborts.forEach(function (abort) { - switch (abort.reason) { - case "marker": { - filteredAborts.push({ - type: "marker", - name: abort.name, - endTime: endTime - }); - break; - } + function updateSuspenseFallbackChildren( + current, + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes + ) { + var mode = workInProgress.mode; + var currentPrimaryChildFragment = current.child; + var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; + var primaryChildProps = { + mode: "hidden", + children: primaryChildren + }; + var primaryChildFragment; - case "suspense": { - filteredAborts.push({ - type: "suspense", - name: abort.name, - endTime: endTime - }); - break; - } - } - }); + if ( + // In legacy mode, we commit the primary tree as if it successfully + // completed, even though it's in an inconsistent state. + (mode & ConcurrentMode) === NoMode && // Make sure we're on the second pass, i.e. the primary child fragment was + // already cloned. In legacy mode, the only case where this isn't true is + // when DevTools forces us to display a fallback; we skip the first render + // pass entirely and go straight to rendering the fallback. (In Concurrent + // Mode, SuspenseList can also trigger this scenario, but this is a legacy- + // only codepath.) + workInProgress.child !== currentPrimaryChildFragment + ) { + var progressedPrimaryFragment = workInProgress.child; + primaryChildFragment = progressedPrimaryFragment; + primaryChildFragment.childLanes = NoLanes; + primaryChildFragment.pendingProps = primaryChildProps; + + if (workInProgress.mode & ProfileMode) { + // Reset the durations from the first pass so they aren't included in the + // final amounts. This seems counterintuitive, since we're intentionally + // not measuring part of the render phase, but this makes it match what we + // do in Concurrent Mode. + primaryChildFragment.actualDuration = 0; + primaryChildFragment.actualStartTime = -1; + primaryChildFragment.selfBaseDuration = + currentPrimaryChildFragment.selfBaseDuration; + primaryChildFragment.treeBaseDuration = + currentPrimaryChildFragment.treeBaseDuration; + } // The fallback fiber was added as a deletion during the first pass. + // However, since we're going to remain on the fallback, we no longer want + // to delete it. + + workInProgress.deletions = null; + } else { + primaryChildFragment = updateWorkInProgressOffscreenFiber( + currentPrimaryChildFragment, + primaryChildProps + ); // Since we're reusing a current tree, we need to reuse the flags, too. + // (We don't do this in legacy mode, because in legacy mode we don't re-use + // the current tree; see previous branch.) - if (filteredAborts.length > 0) { - onMarkerIncomplete( - transition.name, - markerName, - transition.startTime, - filteredAborts - ); - } - }); - }); + primaryChildFragment.subtreeFlags = + currentPrimaryChildFragment.subtreeFlags & StaticMask; } - var transitionProgress = pendingTransitions.transitionProgress; - var onTransitionProgress = callbacks.onTransitionProgress; - - if (onTransitionProgress != null && transitionProgress !== null) { - transitionProgress.forEach(function (pending, transition) { - onTransitionProgress( - transition.name, - transition.startTime, - endTime, - Array.from(pending.values()) - ); - }); - } + var fallbackChildFragment; - var transitionComplete = pendingTransitions.transitionComplete; - var onTransitionComplete = callbacks.onTransitionComplete; + if (currentFallbackChildFragment !== null) { + fallbackChildFragment = createWorkInProgress( + currentFallbackChildFragment, + fallbackChildren + ); + } else { + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); // Needs a placement effect because the parent (the Suspense boundary) already + // mounted but this is a new fiber. - if (transitionComplete !== null && onTransitionComplete != null) { - transitionComplete.forEach(function (transition) { - return onTransitionComplete( - transition.name, - transition.startTime, - endTime - ); - }); + fallbackChildFragment.flags |= Placement; } - } - } -} // For every tracing marker, store a pointer to it. We will later access it -// to get the set of suspense boundaries that need to resolve before the -// tracing marker can be logged as complete -// This code lives separate from the ReactFiberTransition code because -// we push and pop on the tracing marker, not the suspense boundary - -var markerInstanceStack = createCursor(null); -function pushRootMarkerInstance(workInProgress) { - if (enableTransitionTracing) { - // On the root, every transition gets mapped to it's own map of - // suspense boundaries. The transition is marked as complete when - // the suspense boundaries map is empty. We do this because every - // transition completes at different times and depends on different - // suspense boundaries to complete. We store all the transitions - // along with its map of suspense boundaries in the root incomplete - // transitions map. Each entry in this map functions like a tracing - // marker does, so we can push it onto the marker instance stack - var transitions = getWorkInProgressTransitions(); - var root = workInProgress.stateNode; - - if (transitions !== null) { - transitions.forEach(function (transition) { - if (!root.incompleteTransitions.has(transition)) { - var markerInstance = { - tag: TransitionRoot, - transitions: new Set([transition]), - pendingBoundaries: null, - aborts: null, - name: null - }; - root.incompleteTransitions.set(transition, markerInstance); - } - }); + + fallbackChildFragment.return = workInProgress; + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; } - var markerInstances = []; // For ever transition on the suspense boundary, we push the transition - // along with its map of pending suspense boundaries onto the marker - // instance stack. + function retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + recoverableError + ) { + // Falling back to client rendering. Because this has performance + // implications, it's considered a recoverable error, even though the user + // likely won't observe anything wrong with the UI. + // + // The error is passed in as an argument to enforce that every caller provide + // a custom message, or explicitly opt out (currently the only path that opts + // out is legacy mode; every concurrent path provides an error). + if (recoverableError !== null) { + queueHydrationError(recoverableError); + } // This will add the old fiber to the deletion list - root.incompleteTransitions.forEach(function (markerInstance) { - markerInstances.push(markerInstance); - }); - push(markerInstanceStack, markerInstances, workInProgress); - } -} -function popRootMarkerInstance(workInProgress) { - if (enableTransitionTracing) { - pop(markerInstanceStack, workInProgress); - } -} -function pushMarkerInstance(workInProgress, markerInstance) { - if (enableTransitionTracing) { - if (markerInstanceStack.current === null) { - push(markerInstanceStack, [markerInstance], workInProgress); - } else { - push( - markerInstanceStack, - markerInstanceStack.current.concat(markerInstance), - workInProgress - ); - } - } -} -function popMarkerInstance(workInProgress) { - if (enableTransitionTracing) { - pop(markerInstanceStack, workInProgress); - } -} -function getMarkerInstances() { - if (enableTransitionTracing) { - return markerInstanceStack.current; - } + reconcileChildFibers(workInProgress, current.child, null, renderLanes); // We're now not suspended nor dehydrated. - return null; -} + var nextProps = workInProgress.pendingProps; + var primaryChildren = nextProps.children; + var primaryChildFragment = mountSuspensePrimaryChildren( + workInProgress, + primaryChildren + ); // Needs a placement effect because the parent (the Suspense boundary) already + // mounted but this is a new fiber. -var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; // A special exception that's used to unwind the stack when an update flows -// into a dehydrated boundary. - -var SelectiveHydrationException = new Error( - "This is not a real error. It's an implementation detail of React's " + - "selective hydration feature. If this leaks into userspace, it's a bug in " + - "React. Please file an issue." -); -var didReceiveUpdate = false; -var didWarnAboutBadClass; -var didWarnAboutModulePatternComponent; -var didWarnAboutContextTypeOnFunctionComponent; -var didWarnAboutGetDerivedStateOnFunctionComponent; -var didWarnAboutFunctionRefs; -var didWarnAboutReassigningProps; -var didWarnAboutRevealOrder; -var didWarnAboutTailOptions; -var didWarnAboutDefaultPropsOnFunctionComponent; - -{ - didWarnAboutBadClass = {}; - didWarnAboutModulePatternComponent = {}; - didWarnAboutContextTypeOnFunctionComponent = {}; - didWarnAboutGetDerivedStateOnFunctionComponent = {}; - didWarnAboutFunctionRefs = {}; - didWarnAboutReassigningProps = false; - didWarnAboutRevealOrder = {}; - didWarnAboutTailOptions = {}; - didWarnAboutDefaultPropsOnFunctionComponent = {}; -} + primaryChildFragment.flags |= Placement; + workInProgress.memoizedState = null; + return primaryChildFragment; + } -function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { - if (current === null) { - // If this is a fresh new component that hasn't been rendered yet, we - // won't update its child set by applying minimal side-effects. Instead, - // we will add them all to the child before it gets rendered. That means - // we can optimize this reconciliation pass by not tracking side-effects. - workInProgress.child = mountChildFibers( - workInProgress, - null, - nextChildren, - renderLanes - ); - } else { - // If the current child is the same as the work in progress, it means that - // we haven't yet started any work on these children. Therefore, we use - // the clone algorithm to create a copy of all the current children. - // If we had any progressed work already, that is invalid at this point so - // let's throw it out. - workInProgress.child = reconcileChildFibers( + function mountSuspenseFallbackAfterRetryWithoutHydrating( + current, workInProgress, - current.child, - nextChildren, + primaryChildren, + fallbackChildren, renderLanes - ); - } -} + ) { + var fiberMode = workInProgress.mode; + var primaryChildProps = { + mode: "visible", + children: primaryChildren + }; + var primaryChildFragment = mountWorkInProgressOffscreenFiber( + primaryChildProps, + fiberMode + ); + var fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + fiberMode, + renderLanes, + null + ); // Needs a placement effect because the parent (the Suspense + // boundary) already mounted but this is a new fiber. -function forceUnmountCurrentAndReconcile( - current, - workInProgress, - nextChildren, - renderLanes -) { - // This function is fork of reconcileChildren. It's used in cases where we - // want to reconcile without matching against the existing set. This has the - // effect of all current children being unmounted; even if the type and key - // are the same, the old child is unmounted and a new child is created. - // - // To do this, we're going to go through the reconcile algorithm twice. In - // the first pass, we schedule a deletion for all the current children by - // passing null. - workInProgress.child = reconcileChildFibers( - workInProgress, - current.child, - null, - renderLanes - ); // In the second pass, we mount the new children. The trick here is that we - // pass null in place of where we usually pass the current child set. This has - // the effect of remounting all children regardless of whether their - // identities match. - - workInProgress.child = reconcileChildFibers( - workInProgress, - null, - nextChildren, - renderLanes - ); -} + fallbackChildFragment.flags |= Placement; + primaryChildFragment.return = workInProgress; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; -function updateForwardRef( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - // TODO: current can be non-null here even if the component - // hasn't yet mounted. This happens after the first render suspends. - // We'll need to figure out if this is fine or can cause issues. - { - if (workInProgress.type !== workInProgress.elementType) { - // Lazy component props can't be validated in createElement - // because they're only guaranteed to be resolved here. - var innerPropTypes = Component.propTypes; - - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(Component) - ); + if ((workInProgress.mode & ConcurrentMode) !== NoMode) { + // We will have dropped the effect list which contains the + // deletion. We need to reconcile to delete the current child. + reconcileChildFibers(workInProgress, current.child, null, renderLanes); } - } - } - - var render = Component.render; - var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent - var nextChildren; - prepareToReadContext(workInProgress, renderLanes); - - if (enableSchedulingProfiler) { - markComponentRenderStarted(workInProgress); - } + return fallbackChildFragment; + } - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - nextChildren = renderWithHooks( + function updateDehydratedSuspenseComponent( current, workInProgress, - render, + didSuspend, nextProps, - ref, + suspenseInstance, + suspenseState, renderLanes - ); - setIsRendering(false); - } + ) { + if (!didSuspend) { + // This is the first render pass. Attempt to hydrate. + pushPrimaryTreeSuspenseHandler(workInProgress); // We should never be hydrating at this point because it is the first pass, - if (enableSchedulingProfiler) { - markComponentRenderStopped(); - } + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + null + ); + } - if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } + if (isSuspenseInstanceFallback()) { + // This boundary is in a permanent fallback state. In this case, we'll never + // get an update and we'll never be able to hydrate the final content. Let's just try the + // client side render instead. + var digest; + var message, stack; - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + { + var _getSuspenseInstanceF = + getSuspenseInstanceFallbackErrorDetails(); -function updateMemoComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - if (current === null) { - var type = Component.type; + digest = _getSuspenseInstanceF.digest; + message = _getSuspenseInstanceF.message; + stack = _getSuspenseInstanceF.stack; + } - if ( - isSimpleFunctionComponent(type) && - Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. - Component.defaultProps === undefined - ) { - var resolvedType = type; + var capturedValue = null; // TODO: Figure out a better signal than encoding a magic digest value. - { - resolvedType = resolveFunctionForHotReloading(type); - } // If this is a plain function component without default props, - // and with only the default shallow comparison, we upgrade it - // to a SimpleMemoComponent to allow fast path updates. + { + var error; - workInProgress.tag = SimpleMemoComponent; - workInProgress.type = resolvedType; + if (message) { + // eslint-disable-next-line react-internal/prod-error-codes + error = new Error(message); + } else { + error = new Error( + "The server could not finish this Suspense boundary, likely " + + "due to an error during server rendering. Switched to " + + "client rendering." + ); + } - { - validateFunctionComponentInDev(workInProgress, type); - } + error.digest = digest; + capturedValue = createCapturedValue(error, digest, stack); + } - return updateSimpleMemoComponent( - current, - workInProgress, - resolvedType, - nextProps, - renderLanes - ); - } + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + capturedValue + ); + } - { - var innerPropTypes = type.propTypes; - - if (innerPropTypes) { - // Inner memo component props aren't currently validated in createElement. - // We could move it there, but we'd still need this for lazy code path. - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(type) + if ( + enableLazyContextPropagation && // TODO: Factoring is a little weird, since we check this right below, too. + // But don't want to re-arrange the if-else chain until/unless this + // feature lands. + !didReceiveUpdate + ) { + // We need to check if any children have context before we decide to bail + // out, so propagate the changes now. + lazilyPropagateParentContextChanges( + current, + workInProgress, + renderLanes + ); + } // We use lanes to indicate that a child might depend on context, so if + // any context has changed, we need to treat is as if the input might have changed. + + var hasContextChanged = includesSomeLane( + renderLanes, + current.childLanes ); - } - if (Component.defaultProps !== undefined) { - var componentName = getComponentNameFromType(type) || "Unknown"; + if (didReceiveUpdate || hasContextChanged) { + // This boundary has changed since the first render. This means that we are now unable to + // hydrate it. We might still be able to hydrate it using a higher priority lane. + var root = getWorkInProgressRoot(); - if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) { - error( - "%s: Support for defaultProps will be removed from memo components " + - "in a future major release. Use JavaScript default parameters instead.", - componentName + if (root !== null) { + var attemptHydrationAtLane = getBumpedLaneForHydration( + root, + renderLanes + ); + + if ( + attemptHydrationAtLane !== NoLane && + attemptHydrationAtLane !== suspenseState.retryLane + ) { + // Intentionally mutating since this render will get interrupted. This + // is one of the very rare times where we mutate the current tree + // during the render phase. + suspenseState.retryLane = attemptHydrationAtLane; + enqueueConcurrentRenderForLane(current, attemptHydrationAtLane); + scheduleUpdateOnFiber(root, current, attemptHydrationAtLane); // Throw a special object that signals to the work loop that it should + // interrupt the current render. + // + // Because we're inside a React-only execution stack, we don't + // strictly need to throw here — we could instead modify some internal + // work loop state. But using an exception means we don't need to + // check for this case on every iteration of the work loop. So doing + // it this way moves the check out of the fast path. + + throw SelectiveHydrationException; + } + } // If we did not selectively hydrate, we'll continue rendering without + // hydrating. Mark this tree as suspended to prevent it from committing + // outside a transition. + // + // This path should only happen if the hydration lane already suspended. + // Currently, it also happens during sync updates because there is no + // hydration lane for sync updates. + // TODO: We should ideally have a sync hydration lane that we can apply to do + // a pass where we hydrate this subtree in place using the previous Context and then + // reapply the update afterwards. + + if (isSuspenseInstancePending()); + else { + renderDidSuspendDelayIfPossible(); + } + + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + null ); + } else if (isSuspenseInstancePending()) { + // This component is still pending more data from the server, so we can't hydrate its + // content. We treat it as if this component suspended itself. It might seem as if + // we could just try to render it client-side instead. However, this will perform a + // lot of unnecessary work and is unlikely to complete since it often will suspend + // on missing data anyway. Additionally, the server might be able to render more + // than we can on the client yet. In that case we'd end up with more fallback states + // on the client than if we just leave it alone. If the server times out or errors + // these should update this boundary to the permanent Fallback state instead. + // Mark it as having captured (i.e. suspended). + workInProgress.flags |= DidCapture; // Leave the child in place. I.e. the dehydrated fragment. + + workInProgress.child = current.child; // Register a callback to retry this boundary once the server has sent the result. + + retryDehydratedSuspenseBoundary.bind(null, current); + registerSuspenseInstanceRetry(); + return null; + } else { + var primaryChildren = nextProps.children; + var primaryChildFragment = mountSuspensePrimaryChildren( + workInProgress, + primaryChildren + ); // Mark the children as hydrating. This is a fast path to know whether this + // tree is part of a hydrating tree. This is used to determine if a child + // node has fully mounted yet, and for scheduling event replaying. + // Conceptually this is similar to Placement in that a new subtree is + // inserted into the React tree here. It just happens to not need DOM + // mutations because it already exists. - didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true; + primaryChildFragment.flags |= Hydrating; + return primaryChildFragment; } - } - } + } else { + // This is the second render pass. We already attempted to hydrated, but + // something either suspended or errored. + if (workInProgress.flags & ForceClientRender) { + // Something errored during hydration. Try again without hydrating. + pushPrimaryTreeSuspenseHandler(workInProgress); + workInProgress.flags &= ~ForceClientRender; + + var _capturedValue = createCapturedValue( + new Error( + "There was an error while hydrating this Suspense boundary. " + + "Switched to client rendering." + ) + ); - var child = createFiberFromTypeAndProps( - Component.type, - null, - nextProps, - null, - workInProgress, - workInProgress.mode, - renderLanes - ); - child.ref = workInProgress.ref; - child.return = workInProgress; - workInProgress.child = child; - return child; - } - - { - var _type = Component.type; - var _innerPropTypes = _type.propTypes; - - if (_innerPropTypes) { - // Inner memo component props aren't currently validated in createElement. - // We could move it there, but we'd still need this for lazy code path. - checkPropTypes( - _innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(_type) - ); + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + _capturedValue + ); + } else if (workInProgress.memoizedState !== null) { + // Something suspended and we should still be in dehydrated mode. + // Leave the existing child in place. + // Push to avoid a mismatch + pushFallbackTreeSuspenseHandler(workInProgress); + workInProgress.child = current.child; // The dehydrated completion pass expects this flag to be there + // but the normal suspense pass doesn't. + + workInProgress.flags |= DidCapture; + return null; + } else { + // Suspended but we should no longer be in dehydrated mode. + // Therefore we now have to render the fallback. + pushFallbackTreeSuspenseHandler(workInProgress); + var nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; + var fallbackChildFragment = + mountSuspenseFallbackAfterRetryWithoutHydrating( + current, + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); + var _primaryChildFragment4 = workInProgress.child; + _primaryChildFragment4.memoizedState = + mountSuspenseOffscreenState(renderLanes); + workInProgress.memoizedState = SUSPENDED_MARKER; + return fallbackChildFragment; + } + } } - } - var currentChild = current.child; // This is always exactly one child + function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { + fiber.lanes = mergeLanes(fiber.lanes, renderLanes); + var alternate = fiber.alternate; - var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( - current, - renderLanes - ); - - if (!hasScheduledUpdateOrContext) { - // This will be the props with resolved defaultProps, - // unlike current.memoizedProps which will be the unresolved ones. - var prevProps = currentChild.memoizedProps; // Default to shallow comparison - - var compare = Component.compare; - compare = compare !== null ? compare : shallowEqual; + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); + } - if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + scheduleContextWorkOnParentPath( + fiber.return, + renderLanes, + propagationRoot + ); } - } // React DevTools reads this flag. - workInProgress.flags |= PerformedWork; - var newChild = createWorkInProgress(currentChild, nextProps); - newChild.ref = workInProgress.ref; - newChild.return = workInProgress; - workInProgress.child = newChild; - return newChild; -} + function propagateSuspenseContextChange( + workInProgress, + firstChild, + renderLanes + ) { + // Mark any Suspense boundaries with fallbacks as having work to do. + // If they were previously forced into fallbacks, they may now be able + // to unblock. + var node = firstChild; -function updateSimpleMemoComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - // TODO: current can be non-null here even if the component - // hasn't yet mounted. This happens when the inner render suspends. - // We'll need to figure out if this is fine or can cause issues. - { - if (workInProgress.type !== workInProgress.elementType) { - // Lazy component props can't be validated in createElement - // because they're only guaranteed to be resolved here. - var outerMemoType = workInProgress.elementType; - - if (outerMemoType.$$typeof === REACT_LAZY_TYPE) { - // We warn when you define propTypes on lazy() - // so let's just skip over it to find memo() outer wrapper. - // Inner props for memo are validated later. - var lazyComponent = outerMemoType; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + while (node !== null) { + if (node.tag === SuspenseComponent) { + var state = node.memoizedState; - try { - outerMemoType = init(payload); - } catch (x) { - outerMemoType = null; - } // Inner propTypes will be validated in the function component path. + if (state !== null) { + scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); + } + } else if (node.tag === SuspenseListComponent) { + // If the tail is hidden there might not be an Suspense boundaries + // to schedule work on. In this case we have to schedule it on the + // list itself. + // We don't have to traverse to the children of the list since + // the list will propagate the change when it rerenders. + scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } - var outerPropTypes = outerMemoType && outerMemoType.propTypes; + if (node === workInProgress) { + return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - nextProps, // Resolved (SimpleMemoComponent has no defaultProps) - "prop", - getComponentNameFromType(outerMemoType) - ); - } - } - } - } + while (node.sibling === null) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + if (node.return === null || node.return === workInProgress) { + return; + } - if (current !== null) { - var prevProps = current.memoizedProps; + node = node.return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow - if ( - shallowEqual(prevProps, nextProps) && - current.ref === workInProgress.ref && // Prevent bailout if the implementation changed due to hot reload. - workInProgress.type === current.type - ) { - didReceiveUpdate = false; // The props are shallowly equal. Reuse the previous props object, like we - // would during a normal fiber bailout. - // - // We don't have strong guarantees that the props object is referentially - // equal during updates where we can't bail out anyway — like if the props - // are shallowly equal, but there's a local state or context update in the - // same batch. - // - // However, as a principle, we should aim to make the behavior consistent - // across different ways of memoizing a component. For example, React.memo - // has a different internal Fiber layout if you pass a normal function - // component (SimpleMemoComponent) versus if you pass a different type - // like forwardRef (MemoComponent). But this is an implementation detail. - // Wrapping a component in forwardRef (or React.lazy, etc) shouldn't - // affect whether the props object is reused during a bailout. - - workInProgress.pendingProps = nextProps = prevProps; - - if (!checkScheduledUpdateOrContext(current, renderLanes)) { - // The pending lanes were cleared at the beginning of beginWork. We're - // about to bail out, but there might be other lanes that weren't - // included in the current render. Usually, the priority level of the - // remaining updates is accumulated during the evaluation of the - // component (i.e. when processing the update queue). But since since - // we're bailing out early *without* evaluating the component, we need - // to account for it here, too. Reset to the value of the current fiber. - // NOTE: This only applies to SimpleMemoComponent, not MemoComponent, - // because a MemoComponent fiber does not have hooks or an update queue; - // rather, it wraps around an inner component, which may or may not - // contains hooks. - // TODO: Move the reset at in beginWork out of the common path so that - // this is no longer necessary. - workInProgress.lanes = current.lanes; - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - ); - } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags$1) { - // This is a special case that only exists for legacy mode. - // See https://github.com/facebook/react/pull/19216. - didReceiveUpdate = true; + node.sibling.return = node.return; + node = node.sibling; } } - } - return updateFunctionComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes - ); -} + function findLastContentRow(firstChild) { + // This is going to find the last row among these children that is already + // showing content on the screen, as opposed to being in fallback state or + // new. If a row has multiple Suspense boundaries, any of them being in the + // fallback state, counts as the whole row being in a fallback state. + // Note that the "rows" will be workInProgress, but any nested children + // will still be current since we haven't rendered them yet. The mounted + // order may not be the same as the new order. We use the new order. + var row = firstChild; + var lastContentRow = null; -function updateOffscreenComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; - var nextChildren = nextProps.children; - var nextIsDetached = - (workInProgress.stateNode._pendingVisibility & OffscreenDetached) !== 0; - var prevState = current !== null ? current.memoizedState : null; - markRef$1(current, workInProgress); - - if ( - nextProps.mode === "hidden" || - nextProps.mode === "unstable-defer-without-hiding" || - nextIsDetached - ) { - // Rendering a hidden tree. - var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags$1; - - if (didSuspend) { - // Something suspended inside a hidden tree - // Include the base lanes from the last render - var nextBaseLanes = - prevState !== null - ? mergeLanes(prevState.baseLanes, renderLanes) - : renderLanes; + while (row !== null) { + var currentRow = row.alternate; // New rows can't be content rows. - if (current !== null) { - // Reset to the current children - var currentChild = (workInProgress.child = current.child); // The current render suspended, but there may be other lanes with - // pending work. We can't read `childLanes` from the current Offscreen - // fiber because we reset it when it was deferred; however, we can read - // the pending lanes from the child fibers. - - var currentChildLanes = NoLanes; - - while (currentChild !== null) { - currentChildLanes = mergeLanes( - mergeLanes(currentChildLanes, currentChild.lanes), - currentChild.childLanes - ); - currentChild = currentChild.sibling; + if (currentRow !== null && findFirstSuspended(currentRow) === null) { + lastContentRow = row; } - var lanesWeJustAttempted = nextBaseLanes; - var remainingChildLanes = removeLanes( - currentChildLanes, - lanesWeJustAttempted - ); - workInProgress.childLanes = remainingChildLanes; - } else { - workInProgress.childLanes = NoLanes; - workInProgress.child = null; + row = row.sibling; } - return deferHiddenOffscreenComponent( - current, - workInProgress, - nextBaseLanes, - renderLanes - ); + return lastContentRow; } - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - // In legacy sync mode, don't defer the subtree. Render it now. - // TODO: Consider how Offscreen should work with transitions in the future - var nextState = { - baseLanes: NoLanes, - cachePool: null - }; - workInProgress.memoizedState = nextState; - + function validateRevealOrder(revealOrder) { { - // push the cache pool even though we're going to bail out - // because otherwise there'd be a context mismatch - if (current !== null) { - pushTransition(workInProgress, null, null); - } - } + if ( + revealOrder !== undefined && + revealOrder !== "forwards" && + revealOrder !== "backwards" && + revealOrder !== "together" && + !didWarnAboutRevealOrder[revealOrder] + ) { + didWarnAboutRevealOrder[revealOrder] = true; - reuseHiddenContextOnStack(workInProgress); - pushOffscreenSuspenseHandler(workInProgress); - } else if (!includesSomeLane(renderLanes, OffscreenLane)) { - // We're hidden, and we're not rendering at Offscreen. We will bail out - // and resume this tree later. - // Schedule this fiber to re-render at Offscreen priority - workInProgress.lanes = workInProgress.childLanes = - laneToLanes(OffscreenLane); // Include the base lanes from the last render - - var _nextBaseLanes = - prevState !== null - ? mergeLanes(prevState.baseLanes, renderLanes) - : renderLanes; - - return deferHiddenOffscreenComponent( - current, - workInProgress, - _nextBaseLanes, - renderLanes - ); - } else { - // This is the second render. The surrounding visible content has already - // committed. Now we resume rendering the hidden tree. - // Rendering at offscreen, so we can clear the base lanes. - var _nextState = { - baseLanes: NoLanes, - cachePool: null - }; - workInProgress.memoizedState = _nextState; + if (typeof revealOrder === "string") { + switch (revealOrder.toLowerCase()) { + case "together": + case "forwards": + case "backwards": { + error( + '"%s" is not a valid value for revealOrder on . ' + + 'Use lowercase "%s" instead.', + revealOrder, + revealOrder.toLowerCase() + ); - if (current !== null) { - // If the render that spawned this one accessed the cache pool, resume - // using the same cache. Unless the parent changed, since that means - // there was a refresh. - var prevCachePool = prevState !== null ? prevState.cachePool : null; // TODO: Consider if and how Offscreen pre-rendering should - // be attributed to the transition that spawned it + break; + } - pushTransition(workInProgress, prevCachePool, null); - } // Push the lanes that were skipped when we bailed out. + case "forward": + case "backward": { + error( + '"%s" is not a valid value for revealOrder on . ' + + 'React uses the -s suffix in the spelling. Use "%ss" instead.', + revealOrder, + revealOrder.toLowerCase() + ); - if (prevState !== null) { - pushHiddenContext(workInProgress, prevState); - } else { - reuseHiddenContextOnStack(workInProgress); - } + break; + } - pushOffscreenSuspenseHandler(workInProgress); - } - } else { - // Rendering a visible tree. - if (prevState !== null) { - // We're going from hidden -> visible. - var _prevCachePool = null; + default: + error( + '"%s" is not a supported revealOrder on . ' + + 'Did you mean "together", "forwards" or "backwards"?', + revealOrder + ); - { - // If the render that spawned this one accessed the cache pool, resume - // using the same cache. Unless the parent changed, since that means - // there was a refresh. - _prevCachePool = prevState.cachePool; + break; + } + } else { + error( + "%s is not a supported value for revealOrder on . " + + 'Did you mean "together", "forwards" or "backwards"?', + revealOrder + ); + } + } } + } - var transitions = null; + function validateTailOptions(tailMode, revealOrder) { + { + if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) { + if (tailMode !== "collapsed" && tailMode !== "hidden") { + didWarnAboutTailOptions[tailMode] = true; - if (enableTransitionTracing) { - // We have now gone from hidden to visible, so any transitions should - // be added to the stack to get added to any Offscreen/suspense children - var instance = workInProgress.stateNode; + error( + '"%s" is not a supported value for tail on . ' + + 'Did you mean "collapsed" or "hidden"?', + tailMode + ); + } else if ( + revealOrder !== "forwards" && + revealOrder !== "backwards" + ) { + didWarnAboutTailOptions[tailMode] = true; - if (instance !== null && instance._transitions != null) { - transitions = Array.from(instance._transitions); + error( + ' is only valid if revealOrder is ' + + '"forwards" or "backwards". ' + + 'Did you mean to specify revealOrder="forwards"?', + tailMode + ); + } } } + } + + function validateSuspenseListNestedChild(childSlot, index) { + { + var isAnArray = isArray(childSlot); + var isIterable = + !isAnArray && typeof getIteratorFn(childSlot) === "function"; - pushTransition(workInProgress, _prevCachePool, transitions); // Push the lanes that were skipped when we bailed out. + if (isAnArray || isIterable) { + var type = isAnArray ? "array" : "iterable"; - pushHiddenContext(workInProgress, prevState); - reuseSuspenseHandlerOnStack(workInProgress); // Since we're not hidden anymore, reset the state + error( + "A nested %s was passed to row #%s in . Wrap it in " + + "an additional SuspenseList to configure its revealOrder: " + + " ... " + + "{%s} ... " + + "", + type, + index, + type + ); - workInProgress.memoizedState = null; - } else { - // We weren't previously hidden, and we still aren't, so there's nothing - // special to do. Need to push to the stack regardless, though, to avoid - // a push/pop misalignment. - { - // If the render that spawned this one accessed the cache pool, resume - // using the same cache. Unless the parent changed, since that means - // there was a refresh. - if (current !== null) { - pushTransition(workInProgress, null, null); + return false; } - } // We're about to bail out, but we need to push this to the stack anyway - // to avoid a push/pop misalignment. + } - reuseHiddenContextOnStack(workInProgress); - reuseSuspenseHandlerOnStack(workInProgress); + return true; } - } - - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} -function deferHiddenOffscreenComponent( - current, - workInProgress, - nextBaseLanes, - renderLanes -) { - var nextState = { - baseLanes: nextBaseLanes, - // Save the cache pool so we can resume later. - cachePool: getOffscreenDeferredCache() - }; - workInProgress.memoizedState = nextState; - - { - // push the cache pool even though we're going to bail out - // because otherwise there'd be a context mismatch - if (current !== null) { - pushTransition(workInProgress, null, null); - } - } // We're about to bail out, but we need to push this to the stack anyway - // to avoid a push/pop misalignment. - - reuseHiddenContextOnStack(workInProgress); - pushOffscreenSuspenseHandler(workInProgress); - - if (enableLazyContextPropagation && current !== null) { - // Since this tree will resume rendering in a separate render, we need - // to propagate parent contexts now so we don't lose track of which - // ones changed. - propagateParentContextChangesToDeferredTree( - current, - workInProgress, - renderLanes - ); - } + function validateSuspenseListChildren(children, revealOrder) { + { + if ( + (revealOrder === "forwards" || revealOrder === "backwards") && + children !== undefined && + children !== null && + children !== false + ) { + if (isArray(children)) { + for (var i = 0; i < children.length; i++) { + if (!validateSuspenseListNestedChild(children[i], i)) { + return; + } + } + } else { + var iteratorFn = getIteratorFn(children); - return null; -} // Note: These happen to have identical begin phases, for now. We shouldn't hold -// ourselves to this constraint, though. If the behavior diverges, we should -// fork the function. + if (typeof iteratorFn === "function") { + var childrenIterator = iteratorFn.call(children); -var updateLegacyHiddenComponent = updateOffscreenComponent; + if (childrenIterator) { + var step = childrenIterator.next(); + var _i = 0; -function updateCacheComponent(current, workInProgress, renderLanes) { - prepareToReadContext(workInProgress, renderLanes); - var parentCache = readContext(CacheContext); + for (; !step.done; step = childrenIterator.next()) { + if (!validateSuspenseListNestedChild(step.value, _i)) { + return; + } - if (current === null) { - // Initial mount. Request a fresh cache from the pool. - var freshCache = requestCacheFromPool(renderLanes); - var initialState = { - parent: parentCache, - cache: freshCache - }; - workInProgress.memoizedState = initialState; - initializeUpdateQueue(workInProgress); - pushCacheProvider(workInProgress, freshCache); - } else { - // Check for updates - if (includesSomeLane(current.lanes, renderLanes)) { - cloneUpdateQueue(current, workInProgress); - processUpdateQueue(workInProgress, null, null, renderLanes); + _i++; + } + } + } else { + error( + 'A single row was passed to a . ' + + "This is not useful since it needs multiple rows. " + + "Did you mean to pass multiple children or an array?", + revealOrder + ); + } + } + } + } } - var prevState = current.memoizedState; - var nextState = workInProgress.memoizedState; // Compare the new parent cache to the previous to see detect there was - // a refresh. - - if (prevState.parent !== parentCache) { - // Refresh in parent. Update the parent. - var derivedState = { - parent: parentCache, - cache: parentCache - }; // Copied from getDerivedStateFromProps implementation. Once the update - // queue is empty, persist the derived state onto the base state. - - workInProgress.memoizedState = derivedState; + function initSuspenseListRenderState( + workInProgress, + isBackwards, + tail, + lastContentRow, + tailMode + ) { + var renderState = workInProgress.memoizedState; - if (workInProgress.lanes === NoLanes) { - var updateQueue = workInProgress.updateQueue; - workInProgress.memoizedState = updateQueue.baseState = derivedState; - } + if (renderState === null) { + workInProgress.memoizedState = { + isBackwards: isBackwards, + rendering: null, + renderingStartTime: 0, + last: lastContentRow, + tail: tail, + tailMode: tailMode + }; + } else { + // We can reuse the existing object from previous renders. + renderState.isBackwards = isBackwards; + renderState.rendering = null; + renderState.renderingStartTime = 0; + renderState.last = lastContentRow; + renderState.tail = tail; + renderState.tailMode = tailMode; + } + } // This can end up rendering this component multiple passes. + // The first pass splits the children fibers into two sets. A head and tail. + // We first render the head. If anything is in fallback state, we do another + // pass through beginWork to rerender all children (including the tail) with + // the force suspend context. If the first render didn't have anything in + // in fallback state. Then we render each row in the tail one-by-one. + // That happens in the completeWork phase without going back to beginWork. + + function updateSuspenseListComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var revealOrder = nextProps.revealOrder; + var tailMode = nextProps.tail; + var newChildren = nextProps.children; + validateRevealOrder(revealOrder); + validateTailOptions(tailMode, revealOrder); + validateSuspenseListChildren(newChildren, revealOrder); + reconcileChildren(current, workInProgress, newChildren, renderLanes); + var suspenseContext = suspenseStackCursor.current; + var shouldForceFallback = hasSuspenseListContext( + suspenseContext, + ForceSuspenseFallback + ); - pushCacheProvider(workInProgress, parentCache); // No need to propagate a context change because the refreshed parent - // already did. - } else { - // The parent didn't refresh. Now check if this cache did. - var nextCache = nextState.cache; - pushCacheProvider(workInProgress, nextCache); + if (shouldForceFallback) { + suspenseContext = setShallowSuspenseListContext( + suspenseContext, + ForceSuspenseFallback + ); + workInProgress.flags |= DidCapture; + } else { + var didSuspendBefore = + current !== null && (current.flags & DidCapture) !== NoFlags$1; + + if (didSuspendBefore) { + // If we previously forced a fallback, we need to schedule work + // on any nested boundaries to let them know to try to render + // again. This is the same as context updating. + propagateSuspenseContextChange( + workInProgress, + workInProgress.child, + renderLanes + ); + } - if (nextCache !== prevState.cache) { - // This cache refreshed. Propagate a context change. - propagateContextChange(workInProgress, CacheContext, renderLanes); + suspenseContext = setDefaultShallowSuspenseListContext(suspenseContext); } - } - } - var nextChildren = workInProgress.pendingProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} // This should only be called if the name changes - -function updateTracingMarkerComponent(current, workInProgress, renderLanes) { - if (!enableTransitionTracing) { - return null; - } // TODO: (luna) Only update the tracing marker if it's newly rendered or it's name changed. - // A tracing marker is only associated with the transitions that rendered - // or updated it, so we can create a new set of transitions each time - - if (current === null) { - var currentTransitions = getPendingTransitions(); - - if (currentTransitions !== null) { - var markerInstance = { - tag: TransitionTracingMarker, - transitions: new Set(currentTransitions), - pendingBoundaries: null, - name: workInProgress.pendingProps.name, - aborts: null - }; - workInProgress.stateNode = markerInstance; // We call the marker complete callback when all child suspense boundaries resolve. - // We do this in the commit phase on Offscreen. If the marker has no child suspense - // boundaries, we need to schedule a passive effect to make sure we call the marker - // complete callback. + pushSuspenseListContext(workInProgress, suspenseContext); - workInProgress.flags |= Passive$1; - } - } else { - { - if (current.memoizedProps.name !== workInProgress.pendingProps.name) { - error( - "Changing the name of a tracing marker after mount is not supported. " + - "To remount the tracing marker, pass it a new key." - ); - } - } - } + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + // In legacy mode, SuspenseList doesn't work so we just + // use make it a noop by treating it as the default revealOrder. + workInProgress.memoizedState = null; + } else { + switch (revealOrder) { + case "forwards": { + var lastContentRow = findLastContentRow(workInProgress.child); + var tail; + + if (lastContentRow === null) { + // The whole list is part of the tail. + // TODO: We could fast path by just rendering the tail now. + tail = workInProgress.child; + workInProgress.child = null; + } else { + // Disconnect the tail rows after the content row. + // We're going to render them separately later. + tail = lastContentRow.sibling; + lastContentRow.sibling = null; + } - var instance = workInProgress.stateNode; + initSuspenseListRenderState( + workInProgress, + false, // isBackwards + tail, + lastContentRow, + tailMode + ); + break; + } - if (instance !== null) { - pushMarkerInstance(workInProgress, instance); - } + case "backwards": { + // We're going to find the first row that has existing content. + // At the same time we're going to reverse the list of everything + // we pass in the meantime. That's going to be our tail in reverse + // order. + var _tail = null; + var row = workInProgress.child; + workInProgress.child = null; - var nextChildren = workInProgress.pendingProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + while (row !== null) { + var currentRow = row.alternate; // New rows can't be content rows. -function updateFragment(current, workInProgress, renderLanes) { - var nextChildren = workInProgress.pendingProps; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + if ( + currentRow !== null && + findFirstSuspended(currentRow) === null + ) { + // This is the beginning of the main content. + workInProgress.child = row; + break; + } -function updateMode(current, workInProgress, renderLanes) { - var nextChildren = workInProgress.pendingProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + var nextRow = row.sibling; + row.sibling = _tail; + _tail = row; + row = nextRow; + } // TODO: If workInProgress.child is null, we can continue on the tail immediately. + + initSuspenseListRenderState( + workInProgress, + true, // isBackwards + _tail, + null, // last + tailMode + ); + break; + } -function updateProfiler(current, workInProgress, renderLanes) { - { - workInProgress.flags |= Update; + case "together": { + initSuspenseListRenderState( + workInProgress, + false, // isBackwards + null, // tail + null, // last + undefined + ); + break; + } - { - // Reset effect durations for the next eventual effect phase. - // These are reset during render to allow the DevTools commit hook a chance to read them, - var stateNode = workInProgress.stateNode; - stateNode.effectDuration = 0; - stateNode.passiveEffectDuration = 0; - } - } - - var nextProps = workInProgress.pendingProps; - var nextChildren = nextProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + default: { + // The default reveal order is the same as not having + // a boundary. + workInProgress.memoizedState = null; + } + } + } -function markRef$1(current, workInProgress) { - var ref = workInProgress.ref; - - if ( - (current === null && ref !== null) || - (current !== null && current.ref !== ref) - ) { - // Schedule a Ref effect - workInProgress.flags |= Ref; - workInProgress.flags |= RefStatic; - } -} + return workInProgress.child; + } -function updateFunctionComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - { - if (workInProgress.type !== workInProgress.elementType) { - // Lazy component props can't be validated in createElement - // because they're only guaranteed to be resolved here. - var innerPropTypes = Component.propTypes; - - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(Component) + function updatePortalComponent(current, workInProgress, renderLanes) { + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + var nextChildren = workInProgress.pendingProps; + + if (current === null) { + // Portals are special because we don't append the children during mount + // but at commit. Therefore we need to track insertions which the normal + // flow doesn't do during mount. This doesn't happen at the root because + // the root always starts with a "current" with a null child. + // TODO: Consider unifying this with how the root works. + workInProgress.child = reconcileChildFibers( + workInProgress, + null, + nextChildren, + renderLanes ); + } else { + reconcileChildren(current, workInProgress, nextChildren, renderLanes); } - } - } - var context; + return workInProgress.child; + } - { - var unmaskedContext = getUnmaskedContext(workInProgress, Component, true); - context = getMaskedContext(workInProgress, unmaskedContext); - } + var hasWarnedAboutUsingNoValuePropOnContextProvider = false; - var nextChildren; - prepareToReadContext(workInProgress, renderLanes); + function updateContextProvider(current, workInProgress, renderLanes) { + var providerType = workInProgress.type; + var context = providerType._context; + var newProps = workInProgress.pendingProps; + var oldProps = workInProgress.memoizedProps; + var newValue = newProps.value; - if (enableSchedulingProfiler) { - markComponentRenderStarted(workInProgress); - } + { + if (!("value" in newProps)) { + if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { + hasWarnedAboutUsingNoValuePropOnContextProvider = true; - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - nextChildren = renderWithHooks( - current, - workInProgress, - Component, - nextProps, - context, - renderLanes - ); - setIsRendering(false); - } + error( + "The `value` prop is required for the ``. Did you misspell it or forget to pass it?" + ); + } + } - if (enableSchedulingProfiler) { - markComponentRenderStopped(); - } + var providerPropTypes = workInProgress.type.propTypes; - if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } + if (providerPropTypes) { + checkPropTypes( + providerPropTypes, + newProps, + "prop", + "Context.Provider" + ); + } + } - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + pushProvider(workInProgress, context, newValue); -function replayFunctionComponent( - current, - workInProgress, - nextProps, - Component, - secondArg, - renderLanes -) { - // This function is used to replay a component that previously suspended, - // after its data resolves. It's a simplified version of - // updateFunctionComponent that reuses the hooks from the previous attempt. - prepareToReadContext(workInProgress, renderLanes); - - if (enableSchedulingProfiler) { - markComponentRenderStarted(workInProgress); - } - - var nextChildren = replaySuspendedComponentWithHooks( - current, - workInProgress, - Component, - nextProps, - secondArg - ); - - if (enableSchedulingProfiler) { - markComponentRenderStopped(); - } - - if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } - - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + if (enableLazyContextPropagation); + else { + if (oldProps !== null) { + var oldValue = oldProps.value; -function updateClassComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - { - // This is used by DevTools to force a boundary to error. - switch (shouldError(workInProgress)) { - case false: { - var _instance = workInProgress.stateNode; - var ctor = workInProgress.type; // TODO This way of resetting the error boundary state is a hack. - // Is there a better way to do this? - - var tempInstance = new ctor( - workInProgress.memoizedProps, - _instance.context - ); - var state = tempInstance.state; + if (objectIs(oldValue, newValue)) { + // No change. Bailout early if children are the same. + if ( + oldProps.children === newProps.children && + !hasContextChanged() + ) { + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + } + } else { + // The context value changed. Search for matching consumers and schedule + // them to update. + propagateContextChange(workInProgress, context, renderLanes); + } + } + } - _instance.updater.enqueueSetState(_instance, state, null); + var newChildren = newProps.children; + reconcileChildren(current, workInProgress, newChildren, renderLanes); + return workInProgress.child; + } - break; - } + var hasWarnedAboutUsingContextAsConsumer = false; - case true: { - workInProgress.flags |= DidCapture; - workInProgress.flags |= ShouldCapture; // eslint-disable-next-line react-internal/prod-error-codes + function updateContextConsumer(current, workInProgress, renderLanes) { + var context = workInProgress.type; // The logic below for Context differs depending on PROD or DEV mode. In + // DEV mode, we create a separate object for Context.Consumer that acts + // like a proxy to Context. This proxy object adds unnecessary code in PROD + // so we use the old behaviour (Context.Consumer references Context) to + // reduce size and overhead. The separate object references context via + // a property called "_context", which also gives us the ability to check + // in DEV mode if this property exists or not and warn if it does not. - var error$1 = new Error("Simulated error coming from DevTools"); - var lane = pickArbitraryLane(renderLanes); - workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); // Schedule the error boundary to re-render using updated state + { + if (context._context === undefined) { + // This may be because it's a Context (rather than a Consumer). + // Or it may be because it's older React where they're the same thing. + // We only want to warn if we're sure it's a new React. + if (context !== context.Consumer) { + if (!hasWarnedAboutUsingContextAsConsumer) { + hasWarnedAboutUsingContextAsConsumer = true; - var update = createClassErrorUpdate( - workInProgress, - createCapturedValueAtFiber(error$1, workInProgress), - lane - ); - enqueueCapturedUpdate(workInProgress, update); - break; + error( + "Rendering directly is not supported and will be removed in " + + "a future major release. Did you mean to render instead?" + ); + } + } + } else { + context = context._context; + } } - } - if (workInProgress.type !== workInProgress.elementType) { - // Lazy component props can't be validated in createElement - // because they're only guaranteed to be resolved here. - var innerPropTypes = Component.propTypes; + var newProps = workInProgress.pendingProps; + var render = newProps.children; - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(Component) - ); + { + if (typeof render !== "function") { + 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." + ); + } } - } - } // Push context providers early to prevent context stack mismatches. - // During mounting we don't know the child context yet as the instance doesn't exist. - // We will invalidate the child context in finishClassComponent() right after rendering. - - var hasContext; - if (isContextProvider(Component)) { - hasContext = true; - pushContextProvider(workInProgress); - } else { - hasContext = false; - } + prepareToReadContext(workInProgress, renderLanes); + var newValue = readContext(context); - prepareToReadContext(workInProgress, renderLanes); - var instance = workInProgress.stateNode; - var shouldUpdate; + if (enableSchedulingProfiler) { + markComponentRenderStarted(workInProgress); + } - if (instance === null) { - resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); // In the initial pass we might need to construct the instance. + var newChildren; - constructClassInstance(workInProgress, Component, nextProps); - mountClassInstance(workInProgress, Component, nextProps, renderLanes); - shouldUpdate = true; - } else if (current === null) { - // In a resume, we'll already have an instance we can reuse. - shouldUpdate = resumeMountClassInstance( - workInProgress, - Component, - nextProps, - renderLanes - ); - } else { - shouldUpdate = updateClassInstance( - current, - workInProgress, - Component, - nextProps, - renderLanes - ); - } - - var nextUnitOfWork = finishClassComponent( - current, - workInProgress, - Component, - shouldUpdate, - hasContext, - renderLanes - ); - - { - var inst = workInProgress.stateNode; - - if (shouldUpdate && inst.props !== nextProps) { - if (!didWarnAboutReassigningProps) { - 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" - ); + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + newChildren = render(newValue); + setIsRendering(false); } - didWarnAboutReassigningProps = true; - } - } + if (enableSchedulingProfiler) { + markComponentRenderStopped(); + } // React DevTools reads this flag. - return nextUnitOfWork; -} + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, newChildren, renderLanes); + return workInProgress.child; + } -function finishClassComponent( - current, - workInProgress, - Component, - shouldUpdate, - hasContext, - renderLanes -) { - // Refs should update even if shouldComponentUpdate returns false - markRef$1(current, workInProgress); - var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags$1; - - if (!shouldUpdate && !didCaptureError) { - // Context providers should defer to sCU for rendering - if (hasContext) { - invalidateContextProvider(workInProgress, Component, false); - } - - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } - - var instance = workInProgress.stateNode; // Rerender - - ReactCurrentOwner$1.current = workInProgress; - var nextChildren; - - if ( - didCaptureError && - typeof Component.getDerivedStateFromError !== "function" - ) { - // If we captured an error, but getDerivedStateFromError is not defined, - // unmount all the children. componentDidCatch will schedule an update to - // re-render a fallback. This is temporary until we migrate everyone to - // the new API. - // TODO: Warn in a future release. - nextChildren = null; + function updateScopeComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } - { - stopProfilerTimerIfRunning(); + function markWorkInProgressReceivedUpdate() { + didReceiveUpdate = true; } - } else { - if (enableSchedulingProfiler) { - markComponentRenderStarted(workInProgress); + function checkIfWorkInProgressReceivedUpdate() { + return didReceiveUpdate; } - { - setIsRendering(true); - nextChildren = instance.render(); - - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + function resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + if (current !== null) { + // A lazy component only mounts if it suspended inside a non- + // concurrent tree, in an inconsistent state. We want to treat it like + // a new mount, even though an empty version of it already committed. + // Disconnect the alternate pointers. + current.alternate = null; + workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - try { - instance.render(); - } finally { - setIsStrictModeForDevtools(false); + workInProgress.flags |= Placement; } } - - setIsRendering(false); - } - - if (enableSchedulingProfiler) { - markComponentRenderStopped(); } - } // React DevTools reads this flag. - - workInProgress.flags |= PerformedWork; - if (current !== null && didCaptureError) { - // If we're recovering from an error, reconcile without reusing any of - // the existing children. Conceptually, the normal children and the children - // that are shown on error are two different sets, so we shouldn't reuse - // normal children even if their identities match. - forceUnmountCurrentAndReconcile( + function bailoutOnAlreadyFinishedWork( current, workInProgress, - nextChildren, renderLanes - ); - } else { - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - } // Memoize state using the values we just used to render. - // TODO: Restructure so we never read values from the instance. + ) { + if (current !== null) { + // Reuse previous dependencies + workInProgress.dependencies = current.dependencies; + } - workInProgress.memoizedState = instance.state; // The context might have changed so we need to recalculate it. + { + // Don't update "base" render times for bailouts. + stopProfilerTimerIfRunning(); + } - if (hasContext) { - invalidateContextProvider(workInProgress, Component, true); - } + markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. - return workInProgress.child; -} + if (!includesSomeLane(renderLanes, workInProgress.childLanes)) { + // The children don't have any work either. We can skip them. + // TODO: Once we add back resuming, we should check if the children are + // a work-in-progress set. If so, we need to transfer their effects. + if (enableLazyContextPropagation && current !== null) { + // Before bailing out, check if there are any context changes in + // the children. + lazilyPropagateParentContextChanges( + current, + workInProgress, + renderLanes + ); + + if (!includesSomeLane(renderLanes, workInProgress.childLanes)) { + return null; + } + } else { + return null; + } + } // This fiber doesn't have work, but its subtree does. Clone the child + // fibers and continue. -function pushHostRootContext(workInProgress) { - var root = workInProgress.stateNode; + cloneChildFibers(current, workInProgress); + return workInProgress.child; + } - if (root.pendingContext) { - pushTopLevelContextObject( - workInProgress, - root.pendingContext, - root.pendingContext !== root.context - ); - } else if (root.context) { - // Should always be set - pushTopLevelContextObject(workInProgress, root.context, false); - } + function remountFiber(current, oldWorkInProgress, newWorkInProgress) { + { + var returnFiber = oldWorkInProgress.return; - pushHostContainer(workInProgress, root.containerInfo); -} + if (returnFiber === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Cannot swap the root fiber."); + } // Disconnect from the old current. + // It will get deleted. -function updateHostRoot(current, workInProgress, renderLanes) { - pushHostRootContext(workInProgress); + current.alternate = null; + oldWorkInProgress.alternate = null; // Connect to the new tree. - if (current === null) { - throw new Error("Should have a current fiber. This is a bug in React."); - } + newWorkInProgress.index = oldWorkInProgress.index; + newWorkInProgress.sibling = oldWorkInProgress.sibling; + newWorkInProgress.return = oldWorkInProgress.return; + newWorkInProgress.ref = oldWorkInProgress.ref; // Replace the child/sibling pointers above it. - var nextProps = workInProgress.pendingProps; - var prevState = workInProgress.memoizedState; - var prevChildren = prevState.element; - cloneUpdateQueue(current, workInProgress); - processUpdateQueue(workInProgress, nextProps, null, renderLanes); - var nextState = workInProgress.memoizedState; - pushRootTransition(workInProgress); + if (oldWorkInProgress === returnFiber.child) { + returnFiber.child = newWorkInProgress; + } else { + var prevSibling = returnFiber.child; - if (enableTransitionTracing) { - pushRootMarkerInstance(workInProgress); - } + if (prevSibling === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Expected parent to have a child."); + } // $FlowFixMe[incompatible-use] found when upgrading Flow - { - var nextCache = nextState.cache; - pushCacheProvider(workInProgress, nextCache); + while (prevSibling.sibling !== oldWorkInProgress) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + prevSibling = prevSibling.sibling; - if (nextCache !== prevState.cache) { - // The root cache refreshed. - propagateContextChange(workInProgress, CacheContext, renderLanes); - } - } // Caution: React DevTools currently depends on this property - // being called "element". + if (prevSibling === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Expected to find the previous sibling."); + } + } // $FlowFixMe[incompatible-use] found when upgrading Flow - var nextChildren = nextState.element; + prevSibling.sibling = newWorkInProgress; + } // Delete the old fiber and place the new one. + // Since the old fiber is disconnected, we have to schedule it manually. - { - if (nextChildren === prevChildren) { - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } + var deletions = returnFiber.deletions; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - } + if (deletions === null) { + returnFiber.deletions = [current]; + returnFiber.flags |= ChildDeletion; + } else { + deletions.push(current); + } - return workInProgress.child; -} + newWorkInProgress.flags |= Placement; // Restart work from the new fiber. -function updateHostComponent$1(current, workInProgress, renderLanes) { - pushHostContext(workInProgress); - - var type = workInProgress.type; - var nextProps = workInProgress.pendingProps; - var prevProps = current !== null ? current.memoizedProps : null; - var nextChildren = nextProps.children; - var isDirectTextChild = shouldSetTextContent(type, nextProps); - - if (isDirectTextChild) { - // We special case a direct text child of a host node. This is a common - // case. We won't handle it as a reified child. We will instead handle - // this in the host environment that also has access to this prop. That - // avoids allocating another HostText fiber and traversing it. - nextChildren = null; - } else if (prevProps !== null && shouldSetTextContent(type, prevProps)) { - // If we're switching from a direct text child to a normal child, or to - // empty, we need to schedule the text content to be reset. - workInProgress.flags |= ContentReset; - } - - markRef$1(current, workInProgress); - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + return newWorkInProgress; + } + } -function updateHostText$1(current, workInProgress) { - // immediately after. + function checkScheduledUpdateOrContext(current, renderLanes) { + // Before performing an early bailout, we must check if there are pending + // updates or context. + var updateLanes = current.lanes; - return null; -} + if (includesSomeLane(updateLanes, renderLanes)) { + return true; + } // No pending update, but because context is propagated lazily, we need + // to check for a context change before we bail out. -function mountLazyComponent( - _current, - workInProgress, - elementType, - renderLanes -) { - resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); - var props = workInProgress.pendingProps; - var lazyComponent = elementType; - var payload = lazyComponent._payload; - var init = lazyComponent._init; - var Component = init(payload); // Store the unwrapped component in the type. - - workInProgress.type = Component; - var resolvedTag = (workInProgress.tag = resolveLazyComponentTag(Component)); - var resolvedProps = resolveDefaultProps(Component, props); - var child; - - switch (resolvedTag) { - case FunctionComponent: { - { - validateFunctionComponentInDev(workInProgress, Component); - workInProgress.type = Component = - resolveFunctionForHotReloading(Component); - } - - child = updateFunctionComponent( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; - } + if (enableLazyContextPropagation) { + var dependencies = current.dependencies; - case ClassComponent: { - { - workInProgress.type = Component = - resolveClassForHotReloading(Component); + if (dependencies !== null && checkIfContextChanged(dependencies)) { + return true; + } } - child = updateClassComponent( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; + return false; } - case ForwardRef: { - { - workInProgress.type = Component = - resolveForwardRefForHotReloading(Component); - } + function attemptEarlyBailoutIfNoScheduledUpdate( + current, + workInProgress, + renderLanes + ) { + // This fiber does not have any pending work. Bailout without entering + // the begin phase. There's still some bookkeeping we that needs to be done + // in this optimized path, mostly pushing stuff onto the stack. + switch (workInProgress.tag) { + case HostRoot: + pushHostRootContext(workInProgress); + pushRootTransition(workInProgress); - child = updateForwardRef( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; - } + if (enableTransitionTracing) { + pushRootMarkerInstance(workInProgress); + } - case MemoComponent: { - { - if (workInProgress.type !== workInProgress.elementType) { - var outerPropTypes = Component.propTypes; + { + var cache = current.memoizedState.cache; + pushCacheProvider(workInProgress, cache); + } + break; - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - resolvedProps, // Resolved for outer only - "prop", - getComponentNameFromType(Component) - ); + case HostSingleton: + case HostComponent: + pushHostContext(workInProgress); + break; + + case ClassComponent: { + var Component = workInProgress.type; + + if (isContextProvider(Component)) { + pushContextProvider(workInProgress); } + + break; } - } - child = updateMemoComponent( - null, - workInProgress, - Component, - resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too - renderLanes - ); - return child; - } - } + case HostPortal: + pushHostContainer( + workInProgress, + workInProgress.stateNode.containerInfo + ); + break; - var hint = ""; + case ContextProvider: { + var newValue = workInProgress.memoizedProps.value; + var context = workInProgress.type._context; + pushProvider(workInProgress, context, newValue); + break; + } - { - if ( - Component !== null && - typeof Component === "object" && - Component.$$typeof === REACT_LAZY_TYPE - ) { - hint = " Did you wrap a component in React.lazy() more than once?"; - } - } // This message intentionally doesn't mention ForwardRef or MemoComponent - // because the fact that it's a separate type of work is an - // implementation detail. - - 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) - ); -} + case Profiler: + { + // Profiler should only call onRender when one of its descendants actually rendered. + var hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); -function mountIncompleteClassComponent( - _current, - workInProgress, - Component, - nextProps, - renderLanes -) { - resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); // Promote the fiber to a class and try rendering again. - - workInProgress.tag = ClassComponent; // The rest of this function is a fork of `updateClassComponent` - // Push context providers early to prevent context stack mismatches. - // During mounting we don't know the child context yet as the instance doesn't exist. - // We will invalidate the child context in finishClassComponent() right after rendering. - - var hasContext; - - if (isContextProvider(Component)) { - hasContext = true; - pushContextProvider(workInProgress); - } else { - hasContext = false; - } - - prepareToReadContext(workInProgress, renderLanes); - constructClassInstance(workInProgress, Component, nextProps); - mountClassInstance(workInProgress, Component, nextProps, renderLanes); - return finishClassComponent( - null, - workInProgress, - Component, - true, - hasContext, - renderLanes - ); -} + if (hasChildWork) { + workInProgress.flags |= Update; + } -function mountIndeterminateComponent( - _current, - workInProgress, - Component, - renderLanes -) { - resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); - var props = workInProgress.pendingProps; - var context; - - { - var unmaskedContext = getUnmaskedContext(workInProgress, Component, false); - context = getMaskedContext(workInProgress, unmaskedContext); - } - - prepareToReadContext(workInProgress, renderLanes); - var value; - - if (enableSchedulingProfiler) { - markComponentRenderStarted(workInProgress); - } - - { - if ( - Component.prototype && - typeof Component.prototype.render === "function" - ) { - var componentName = getComponentNameFromType(Component) || "Unknown"; + { + // Reset effect durations for the next eventual effect phase. + // These are reset during render to allow the DevTools commit hook a chance to read them, + var stateNode = workInProgress.stateNode; + stateNode.effectDuration = 0; + stateNode.passiveEffectDuration = 0; + } + } - if (!didWarnAboutBadClass[componentName]) { - 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 - ); + break; - didWarnAboutBadClass[componentName] = true; - } - } + case SuspenseComponent: { + var state = workInProgress.memoizedState; + + if (state !== null) { + if (state.dehydrated !== null) { + // We're not going to render the children, so this is just to maintain + // push/pop symmetry + pushPrimaryTreeSuspenseHandler(workInProgress); // We know that this component will suspend again because if it has + // been unsuspended it has committed as a resolved Suspense component. + // If it needs to be retried, it should have work scheduled on it. - if (workInProgress.mode & StrictLegacyMode) { - ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null); - } + workInProgress.flags |= DidCapture; // We should never render the children of a dehydrated boundary until we + // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork. - setIsRendering(true); - ReactCurrentOwner$1.current = workInProgress; - value = renderWithHooks( - null, - workInProgress, - Component, - props, - context, - renderLanes - ); - setIsRendering(false); - } + return null; + } // If this boundary is currently timed out, we need to decide + // whether to retry the primary children, or to skip over it and + // go straight to the fallback. Check the priority of the primary + // child fragment. - if (enableSchedulingProfiler) { - markComponentRenderStopped(); - } // React DevTools reads this flag. + var primaryChildFragment = workInProgress.child; + var primaryChildLanes = primaryChildFragment.childLanes; + + if (includesSomeLane(renderLanes, primaryChildLanes)) { + // The primary children have pending work. Use the normal path + // to attempt to render the primary children again. + return updateSuspenseComponent( + current, + workInProgress, + renderLanes + ); + } else { + // The primary child fragment does not have pending work marked + // on it + pushPrimaryTreeSuspenseHandler(workInProgress); // The primary children do not have pending work with sufficient + // priority. Bailout. + + var child = bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + + if (child !== null) { + // The fallback children have pending work. Skip over the + // primary children and work on the fallback. + return child.sibling; + } else { + // Note: We can return `null` here because we already checked + // whether there were nested context consumers, via the call to + // `bailoutOnAlreadyFinishedWork` above. + return null; + } + } + } else { + pushPrimaryTreeSuspenseHandler(workInProgress); + } - workInProgress.flags |= PerformedWork; + break; + } - { - // Support for module components is deprecated and is removed behind a flag. - // Whether or not it would crash later, we want to show a good message in DEV first. - if ( - typeof value === "object" && - value !== null && - typeof value.render === "function" && - value.$$typeof === undefined - ) { - var _componentName = getComponentNameFromType(Component) || "Unknown"; + case SuspenseListComponent: { + var didSuspendBefore = (current.flags & DidCapture) !== NoFlags$1; - if (!didWarnAboutModulePatternComponent[_componentName]) { - 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 - ); + var _hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); - didWarnAboutModulePatternComponent[_componentName] = true; - } - } - } + if (enableLazyContextPropagation && !_hasChildWork) { + // Context changes may not have been propagated yet. We need to do + // that now, before we can decide whether to bail out. + // TODO: We use `childLanes` as a heuristic for whether there is + // remaining work in a few places, including + // `bailoutOnAlreadyFinishedWork` and + // `updateDehydratedSuspenseComponent`. We should maybe extract this + // into a dedicated function. + lazilyPropagateParentContextChanges( + current, + workInProgress, + renderLanes + ); + _hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); + } - { - // Proceed under the assumption that this is a function component - workInProgress.tag = FunctionComponent; + if (didSuspendBefore) { + if (_hasChildWork) { + // If something was in fallback state last time, and we have all the + // same children then we're still in progressive loading state. + // Something might get unblocked by state updates or retries in the + // tree which will affect the tail. So we need to use the normal + // path to compute the correct tail. + return updateSuspenseListComponent( + current, + workInProgress, + renderLanes + ); + } // If none of the children had any work, that means that none of + // them got retried so they'll still be blocked in the same way + // as before. We can fast bail out. - reconcileChildren(null, workInProgress, value, renderLanes); + workInProgress.flags |= DidCapture; + } // If nothing suspended before and we're rendering the same children, + // then the tail doesn't matter. Anything new that suspends will work + // in the "together" mode, so we can continue from the state we had. + + var renderState = workInProgress.memoizedState; + + if (renderState !== null) { + // Reset to the "together" mode in case we've started a different + // update in the past but didn't complete it. + renderState.rendering = null; + renderState.tail = null; + renderState.lastEffect = null; + } - { - validateFunctionComponentInDev(workInProgress, Component); - } + pushSuspenseListContext(workInProgress, suspenseStackCursor.current); - return workInProgress.child; - } -} + if (_hasChildWork) { + break; + } else { + // If none of the children had any work, that means that none of + // them got retried so they'll still be blocked in the same way + // as before. We can fast bail out. + return null; + } + } -function validateFunctionComponentInDev(workInProgress, Component) { - { - if (Component) { - if (Component.childContextTypes) { - error( - "%s(...): childContextTypes cannot be defined on a function component.", - Component.displayName || Component.name || "Component" - ); - } - } + case OffscreenComponent: + case LegacyHiddenComponent: { + // Need to check if the tree still needs to be deferred. This is + // almost identical to the logic used in the normal update path, + // so we'll just enter that. The only difference is we'll bail out + // at the next level instead of this one, because the child props + // have not changed. Which is fine. + // TODO: Probably should refactor `beginWork` to split the bailout + // path from the normal path. I'm tempted to do a labeled break here + // but I won't :) + workInProgress.lanes = NoLanes; + return updateOffscreenComponent(current, workInProgress, renderLanes); + } - if (workInProgress.ref !== null) { - var info = ""; - var ownerName = getCurrentFiberOwnerNameInDevOrNull(); + case CacheComponent: { + { + var _cache = current.memoizedState.cache; + pushCacheProvider(workInProgress, _cache); + } - if (ownerName) { - info += "\n\nCheck the render method of `" + ownerName + "`."; - } + break; + } - var warningKey = ownerName || ""; - var debugSource = workInProgress._debugSource; + case TracingMarkerComponent: { + if (enableTransitionTracing) { + var instance = workInProgress.stateNode; - if (debugSource) { - warningKey = debugSource.fileName + ":" + debugSource.lineNumber; + if (instance !== null) { + pushMarkerInstance(workInProgress, instance); + } + } + } } - if (!didWarnAboutFunctionRefs[warningKey]) { - didWarnAboutFunctionRefs[warningKey] = true; + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + } - error( - "Function components cannot be given refs. " + - "Attempts to access this ref will fail. " + - "Did you mean to use React.forwardRef()?%s", - info - ); + function beginWork$1(current, workInProgress, renderLanes) { + { + if (workInProgress._debugNeedsRemount && current !== null) { + // This will restart the begin phase with a new fiber. + return remountFiber( + current, + workInProgress, + createFiberFromTypeAndProps( + workInProgress.type, + workInProgress.key, + workInProgress.pendingProps, + workInProgress._debugSource || null, + workInProgress._debugOwner || null, + workInProgress.mode, + workInProgress.lanes + ) + ); + } } - } - if (Component.defaultProps !== undefined) { - var componentName = getComponentNameFromType(Component) || "Unknown"; + if (current !== null) { + var oldProps = current.memoizedProps; + var newProps = workInProgress.pendingProps; - if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) { - error( - "%s: Support for defaultProps will be removed from function components " + - "in a future major release. Use JavaScript default parameters instead.", - componentName - ); + if ( + oldProps !== newProps || + hasContextChanged() || // Force a re-render if the implementation changed due to hot reload: + workInProgress.type !== current.type + ) { + // If props or context changed, mark the fiber as having performed work. + // This may be unset if the props are determined to be equal later (memo). + didReceiveUpdate = true; + } else { + // Neither props nor legacy context changes. Check if there's a pending + // update or context change. + var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( + current, + renderLanes + ); - didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true; - } - } + if ( + !hasScheduledUpdateOrContext && // If this is the second pass of an error or suspense boundary, there + // may not be work scheduled on `current`, so we check for this flag. + (workInProgress.flags & DidCapture) === NoFlags$1 + ) { + // No pending updates or context. Bail out now. + didReceiveUpdate = false; + return attemptEarlyBailoutIfNoScheduledUpdate( + current, + workInProgress, + renderLanes + ); + } - if (typeof Component.getDerivedStateFromProps === "function") { - var _componentName3 = getComponentNameFromType(Component) || "Unknown"; + if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags$1) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; + } else { + // An update was scheduled on this fiber, but there are no new props + // nor legacy context. Set this to false. If an update queue or context + // consumer produces a changed value, it will set this to true. Otherwise, + // the component will assume the children have not changed and bail out. + didReceiveUpdate = false; + } + } + } else { + didReceiveUpdate = false; + } // Before entering the begin phase, clear pending update priority. + // TODO: This assumes that we're about to evaluate the component and process + // the update queue. However, there's an exception: SimpleMemoComponent + // sometimes bails out later in the begin phase. This indicates that we should + // move this assignment out of the common path and into each branch. - if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { - error( - "%s: Function components do not support getDerivedStateFromProps.", - _componentName3 - ); + workInProgress.lanes = NoLanes; - didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true; - } - } + switch (workInProgress.tag) { + case IndeterminateComponent: { + return mountIndeterminateComponent( + current, + workInProgress, + workInProgress.type, + renderLanes + ); + } - if ( - typeof Component.contextType === "object" && - Component.contextType !== null - ) { - var _componentName4 = getComponentNameFromType(Component) || "Unknown"; + case LazyComponent: { + var elementType = workInProgress.elementType; + return mountLazyComponent( + current, + workInProgress, + elementType, + renderLanes + ); + } - if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { - error( - "%s: Function components do not support contextType.", - _componentName4 - ); + case FunctionComponent: { + var Component = workInProgress.type; + var unresolvedProps = workInProgress.pendingProps; + var resolvedProps = + workInProgress.elementType === Component + ? unresolvedProps + : resolveDefaultProps(Component, unresolvedProps); + return updateFunctionComponent( + current, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + } - didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; - } - } - } -} + case ClassComponent: { + var _Component = workInProgress.type; + var _unresolvedProps = workInProgress.pendingProps; -var SUSPENDED_MARKER = { - dehydrated: null, - treeContext: null, - retryLane: NoLane -}; - -function mountSuspenseOffscreenState(renderLanes) { - return { - baseLanes: renderLanes, - cachePool: getSuspendedCache() - }; -} + var _resolvedProps = + workInProgress.elementType === _Component + ? _unresolvedProps + : resolveDefaultProps(_Component, _unresolvedProps); -function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { - var cachePool = null; + return updateClassComponent( + current, + workInProgress, + _Component, + _resolvedProps, + renderLanes + ); + } - { - var prevCachePool = prevOffscreenState.cachePool; + case HostRoot: + return updateHostRoot(current, workInProgress, renderLanes); - if (prevCachePool !== null) { - var parentCache = CacheContext._currentValue2; + case HostHoistable: - if (prevCachePool.parent !== parentCache) { - // Detected a refresh in the parent. This overrides any previously - // suspended cache. - cachePool = { - parent: parentCache, - pool: parentCache - }; - } else { - // We can reuse the cache from last time. The only thing that would have - // overridden it is a parent refresh, which we checked for above. - cachePool = prevCachePool; - } - } else { - // If there's no previous cache pool, grab the current one. - cachePool = getSuspendedCache(); - } - } - - return { - baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), - cachePool: cachePool - }; -} // TODO: Probably should inline this back - -function shouldRemainOnFallback(current, workInProgress, renderLanes) { - // If we're already showing a fallback, there are cases where we need to - // remain on that fallback regardless of whether the content has resolved. - // For example, SuspenseList coordinates when nested content appears. - // TODO: For compatibility with offscreen prerendering, this should also check - // whether the current fiber (if it exists) was visible in the previous tree. - if (current !== null) { - var suspenseState = current.memoizedState; - - if (suspenseState === null) { - // Currently showing content. Don't hide it, even if ForceSuspenseFallback - // is true. More precise name might be "ForceRemainSuspenseFallback". - // Note: This is a factoring smell. Can't remain on a fallback if there's - // no fallback to remain on. - return false; - } - } // Not currently showing content. Consult the Suspense context. + // Fall through - var suspenseContext = suspenseStackCursor.current; - return hasSuspenseListContext(suspenseContext, ForceSuspenseFallback); -} + case HostSingleton: -function getRemainingWorkInPrimaryTree(current, renderLanes) { - // TODO: Should not remove render lanes that were pinged during this render - return removeLanes(current.childLanes, renderLanes); -} + // Fall through -function updateSuspenseComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend. - - { - if (shouldSuspend(workInProgress)) { - workInProgress.flags |= DidCapture; - } - } - - var showFallback = false; - var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags$1; - - if (didSuspend || shouldRemainOnFallback(current)) { - // Something in this boundary's subtree already suspended. Switch to - // rendering the fallback children. - showFallback = true; - workInProgress.flags &= ~DidCapture; - } // OK, the next part is confusing. We're about to reconcile the Suspense - // boundary's children. This involves some custom reconciliation logic. Two - // main reasons this is so complicated. - // - // First, Legacy Mode has different semantics for backwards compatibility. The - // primary tree will commit in an inconsistent state, so when we do the - // second pass to render the fallback, we do some exceedingly, uh, clever - // hacks to make that not totally break. Like transferring effects and - // deletions from hidden tree. In Concurrent Mode, it's much simpler, - // because we bailout on the primary tree completely and leave it in its old - // state, no effects. Same as what we do for Offscreen (except that - // Offscreen doesn't have the first render pass). - // - // Second is hydration. During hydration, the Suspense fiber has a slightly - // different layout, where the child points to a dehydrated fragment, which - // contains the DOM rendered by the server. - // - // Third, even if you set all that aside, Suspense is like error boundaries in - // that we first we try to render one tree, and if that fails, we render again - // and switch to a different tree. Like a try/catch block. So we have to track - // which branch we're currently rendering. Ideally we would model this using - // a stack. - - if (current === null) { - var nextPrimaryChildren = nextProps.children; - var nextFallbackChildren = nextProps.fallback; - - if (showFallback) { - pushFallbackTreeSuspenseHandler(workInProgress); - var fallbackFragment = mountSuspenseFallbackChildren( - workInProgress, - nextPrimaryChildren, - nextFallbackChildren, - renderLanes - ); - var primaryChildFragment = workInProgress.child; - primaryChildFragment.memoizedState = - mountSuspenseOffscreenState(renderLanes); - workInProgress.memoizedState = SUSPENDED_MARKER; + case HostComponent: + return updateHostComponent$1(current, workInProgress, renderLanes); - if (enableTransitionTracing) { - var currentTransitions = getPendingTransitions(); + case HostText: + return updateHostText$1(); - if (currentTransitions !== null) { - var parentMarkerInstances = getMarkerInstances(); - var offscreenQueue = primaryChildFragment.updateQueue; - - if (offscreenQueue === null) { - var newOffscreenQueue = { - transitions: currentTransitions, - markerInstances: parentMarkerInstances, - retryQueue: null - }; - primaryChildFragment.updateQueue = newOffscreenQueue; - } else { - offscreenQueue.transitions = currentTransitions; - offscreenQueue.markerInstances = parentMarkerInstances; - } - } - } + case SuspenseComponent: + return updateSuspenseComponent(current, workInProgress, renderLanes); - return fallbackFragment; - } else if (typeof nextProps.unstable_expectedLoadTime === "number") { - // This is a CPU-bound tree. Skip this tree and show a placeholder to - // unblock the surrounding content. Then immediately retry after the - // initial commit. - pushFallbackTreeSuspenseHandler(workInProgress); + case HostPortal: + return updatePortalComponent(current, workInProgress, renderLanes); - var _fallbackFragment = mountSuspenseFallbackChildren( - workInProgress, - nextPrimaryChildren, - nextFallbackChildren, - renderLanes - ); + case ForwardRef: { + var type = workInProgress.type; + var _unresolvedProps2 = workInProgress.pendingProps; - var _primaryChildFragment = workInProgress.child; - _primaryChildFragment.memoizedState = - mountSuspenseOffscreenState(renderLanes); - workInProgress.memoizedState = SUSPENDED_MARKER; // TODO: Transition Tracing is not yet implemented for CPU Suspense. - // Since nothing actually suspended, there will nothing to ping this to - // get it started back up to attempt the next item. While in terms of - // priority this work has the same priority as this current render, it's - // not part of the same transition once the transition has committed. If - // it's sync, we still want to yield so that it can be painted. - // Conceptually, this is really the same as pinging. We can use any - // RetryLane even if it's the one currently rendering since we're leaving - // it behind on this node. - - workInProgress.lanes = SomeRetryLane; - return _fallbackFragment; - } else { - pushPrimaryTreeSuspenseHandler(workInProgress); - return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren); - } - } else { - // This is an update. - // Special path for hydration - var prevState = current.memoizedState; + var _resolvedProps2 = + workInProgress.elementType === type + ? _unresolvedProps2 + : resolveDefaultProps(type, _unresolvedProps2); - if (prevState !== null) { - var _dehydrated = prevState.dehydrated; + return updateForwardRef( + current, + workInProgress, + type, + _resolvedProps2, + renderLanes + ); + } - if (_dehydrated !== null) { - return updateDehydratedSuspenseComponent( - current, - workInProgress, - didSuspend, - nextProps, - _dehydrated, - prevState, - renderLanes - ); - } - } + case Fragment: + return updateFragment(current, workInProgress, renderLanes); - if (showFallback) { - pushFallbackTreeSuspenseHandler(workInProgress); - var _nextFallbackChildren = nextProps.fallback; - var _nextPrimaryChildren = nextProps.children; - var fallbackChildFragment = updateSuspenseFallbackChildren( - current, - workInProgress, - _nextPrimaryChildren, - _nextFallbackChildren, - renderLanes - ); - var _primaryChildFragment2 = workInProgress.child; - var prevOffscreenState = current.child.memoizedState; - _primaryChildFragment2.memoizedState = - prevOffscreenState === null - ? mountSuspenseOffscreenState(renderLanes) - : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); + case Mode: + return updateMode(current, workInProgress, renderLanes); - if (enableTransitionTracing) { - var _currentTransitions = getPendingTransitions(); + case Profiler: + return updateProfiler(current, workInProgress, renderLanes); - if (_currentTransitions !== null) { - var _parentMarkerInstances = getMarkerInstances(); + case ContextProvider: + return updateContextProvider(current, workInProgress, renderLanes); - var _offscreenQueue = _primaryChildFragment2.updateQueue; - var currentOffscreenQueue = current.updateQueue; + case ContextConsumer: + return updateContextConsumer(current, workInProgress, renderLanes); - if (_offscreenQueue === null) { - var _newOffscreenQueue = { - transitions: _currentTransitions, - markerInstances: _parentMarkerInstances, - retryQueue: null - }; - _primaryChildFragment2.updateQueue = _newOffscreenQueue; - } else if (_offscreenQueue === currentOffscreenQueue) { - // If the work-in-progress queue is the same object as current, we - // can't modify it without cloning it first. - var _newOffscreenQueue2 = { - transitions: _currentTransitions, - markerInstances: _parentMarkerInstances, - retryQueue: - currentOffscreenQueue !== null - ? currentOffscreenQueue.retryQueue - : null - }; - _primaryChildFragment2.updateQueue = _newOffscreenQueue2; - } else { - _offscreenQueue.transitions = _currentTransitions; - _offscreenQueue.markerInstances = _parentMarkerInstances; - } - } - } + case MemoComponent: { + var _type2 = workInProgress.type; + var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. - _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree( - current, - renderLanes - ); - workInProgress.memoizedState = SUSPENDED_MARKER; - return fallbackChildFragment; - } else { - pushPrimaryTreeSuspenseHandler(workInProgress); - var _nextPrimaryChildren2 = nextProps.children; + var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); - var _primaryChildFragment3 = updateSuspensePrimaryChildren( - current, - workInProgress, - _nextPrimaryChildren2, - renderLanes - ); + { + if (workInProgress.type !== workInProgress.elementType) { + var outerPropTypes = _type2.propTypes; + + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + _resolvedProps3, // Resolved for outer only + "prop", + getComponentNameFromType(_type2) + ); + } + } + } - workInProgress.memoizedState = null; - return _primaryChildFragment3; - } - } -} + _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); + return updateMemoComponent( + current, + workInProgress, + _type2, + _resolvedProps3, + renderLanes + ); + } -function mountSuspensePrimaryChildren( - workInProgress, - primaryChildren, - renderLanes -) { - var mode = workInProgress.mode; - var primaryChildProps = { - mode: "visible", - children: primaryChildren - }; - var primaryChildFragment = mountWorkInProgressOffscreenFiber( - primaryChildProps, - mode - ); - primaryChildFragment.return = workInProgress; - workInProgress.child = primaryChildFragment; - return primaryChildFragment; -} + case SimpleMemoComponent: { + return updateSimpleMemoComponent( + current, + workInProgress, + workInProgress.type, + workInProgress.pendingProps, + renderLanes + ); + } -function mountSuspenseFallbackChildren( - workInProgress, - primaryChildren, - fallbackChildren, - renderLanes -) { - var mode = workInProgress.mode; - var progressedPrimaryFragment = workInProgress.child; - var primaryChildProps = { - mode: "hidden", - children: primaryChildren - }; - var primaryChildFragment; - var fallbackChildFragment; - - if ( - (mode & ConcurrentMode) === NoMode && - progressedPrimaryFragment !== null - ) { - // In legacy mode, we commit the primary tree as if it successfully - // completed, even though it's in an inconsistent state. - primaryChildFragment = progressedPrimaryFragment; - primaryChildFragment.childLanes = NoLanes; - primaryChildFragment.pendingProps = primaryChildProps; - - if (workInProgress.mode & ProfileMode) { - // Reset the durations from the first pass so they aren't included in the - // final amounts. This seems counterintuitive, since we're intentionally - // not measuring part of the render phase, but this makes it match what we - // do in Concurrent Mode. - primaryChildFragment.actualDuration = 0; - primaryChildFragment.actualStartTime = -1; - primaryChildFragment.selfBaseDuration = 0; - primaryChildFragment.treeBaseDuration = 0; - } - - fallbackChildFragment = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, - null - ); - } else { - primaryChildFragment = mountWorkInProgressOffscreenFiber( - primaryChildProps, - mode - ); - fallbackChildFragment = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, - null - ); - } + case IncompleteClassComponent: { + var _Component2 = workInProgress.type; + var _unresolvedProps4 = workInProgress.pendingProps; - primaryChildFragment.return = workInProgress; - fallbackChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; - workInProgress.child = primaryChildFragment; - return fallbackChildFragment; -} + var _resolvedProps4 = + workInProgress.elementType === _Component2 + ? _unresolvedProps4 + : resolveDefaultProps(_Component2, _unresolvedProps4); -function mountWorkInProgressOffscreenFiber(offscreenProps, mode, renderLanes) { - // The props argument to `createFiberFromOffscreen` is `any` typed, so we use - // this wrapper function to constrain it. - return createFiberFromOffscreen(offscreenProps, mode, NoLanes, null); -} + return mountIncompleteClassComponent( + current, + workInProgress, + _Component2, + _resolvedProps4, + renderLanes + ); + } -function updateWorkInProgressOffscreenFiber(current, offscreenProps) { - // The props argument to `createWorkInProgress` is `any` typed, so we use this - // wrapper function to constrain it. - return createWorkInProgress(current, offscreenProps); -} + case SuspenseListComponent: { + return updateSuspenseListComponent( + current, + workInProgress, + renderLanes + ); + } -function updateSuspensePrimaryChildren( - current, - workInProgress, - primaryChildren, - renderLanes -) { - var currentPrimaryChildFragment = current.child; - var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; - var primaryChildFragment = updateWorkInProgressOffscreenFiber( - currentPrimaryChildFragment, - { - mode: "visible", - children: primaryChildren - } - ); + case ScopeComponent: { + { + return updateScopeComponent(current, workInProgress, renderLanes); + } + } - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - primaryChildFragment.lanes = renderLanes; - } + case OffscreenComponent: { + return updateOffscreenComponent(current, workInProgress, renderLanes); + } - primaryChildFragment.return = workInProgress; - primaryChildFragment.sibling = null; + case LegacyHiddenComponent: { + { + return updateLegacyHiddenComponent( + current, + workInProgress, + renderLanes + ); + } + } - if (currentFallbackChildFragment !== null) { - // Delete the fallback child fragment - var deletions = workInProgress.deletions; + case CacheComponent: { + { + return updateCacheComponent(current, workInProgress, renderLanes); + } + } - if (deletions === null) { - workInProgress.deletions = [currentFallbackChildFragment]; - workInProgress.flags |= ChildDeletion; - } else { - deletions.push(currentFallbackChildFragment); - } - } + case TracingMarkerComponent: { + if (enableTransitionTracing) { + return updateTracingMarkerComponent( + current, + workInProgress, + renderLanes + ); + } - workInProgress.child = primaryChildFragment; - return primaryChildFragment; -} + break; + } + } -function updateSuspenseFallbackChildren( - current, - workInProgress, - primaryChildren, - fallbackChildren, - renderLanes -) { - var mode = workInProgress.mode; - var currentPrimaryChildFragment = current.child; - var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; - var primaryChildProps = { - mode: "hidden", - children: primaryChildren - }; - var primaryChildFragment; - - if ( - // In legacy mode, we commit the primary tree as if it successfully - // completed, even though it's in an inconsistent state. - (mode & ConcurrentMode) === NoMode && // Make sure we're on the second pass, i.e. the primary child fragment was - // already cloned. In legacy mode, the only case where this isn't true is - // when DevTools forces us to display a fallback; we skip the first render - // pass entirely and go straight to rendering the fallback. (In Concurrent - // Mode, SuspenseList can also trigger this scenario, but this is a legacy- - // only codepath.) - workInProgress.child !== currentPrimaryChildFragment - ) { - var progressedPrimaryFragment = workInProgress.child; - primaryChildFragment = progressedPrimaryFragment; - primaryChildFragment.childLanes = NoLanes; - primaryChildFragment.pendingProps = primaryChildProps; - - if (workInProgress.mode & ProfileMode) { - // Reset the durations from the first pass so they aren't included in the - // final amounts. This seems counterintuitive, since we're intentionally - // not measuring part of the render phase, but this makes it match what we - // do in Concurrent Mode. - primaryChildFragment.actualDuration = 0; - primaryChildFragment.actualStartTime = -1; - primaryChildFragment.selfBaseDuration = - currentPrimaryChildFragment.selfBaseDuration; - primaryChildFragment.treeBaseDuration = - currentPrimaryChildFragment.treeBaseDuration; - } // The fallback fiber was added as a deletion during the first pass. - // However, since we're going to remain on the fallback, we no longer want - // to delete it. - - workInProgress.deletions = null; - } else { - primaryChildFragment = updateWorkInProgressOffscreenFiber( - currentPrimaryChildFragment, - primaryChildProps - ); // Since we're reusing a current tree, we need to reuse the flags, too. - // (We don't do this in legacy mode, because in legacy mode we don't re-use - // the current tree; see previous branch.) - - primaryChildFragment.subtreeFlags = - currentPrimaryChildFragment.subtreeFlags & StaticMask; - } - - var fallbackChildFragment; - - if (currentFallbackChildFragment !== null) { - fallbackChildFragment = createWorkInProgress( - currentFallbackChildFragment, - fallbackChildren - ); - } else { - fallbackChildFragment = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, - null - ); // Needs a placement effect because the parent (the Suspense boundary) already - // mounted but this is a new fiber. - - fallbackChildFragment.flags |= Placement; - } - - fallbackChildFragment.return = workInProgress; - primaryChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; - workInProgress.child = primaryChildFragment; - return fallbackChildFragment; -} + throw new Error( + "Unknown unit of work tag (" + + workInProgress.tag + + "). This error is likely caused by a bug in " + + "React. Please file an issue." + ); + } -function retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - recoverableError -) { - // Falling back to client rendering. Because this has performance - // implications, it's considered a recoverable error, even though the user - // likely won't observe anything wrong with the UI. - // - // The error is passed in as an argument to enforce that every caller provide - // a custom message, or explicitly opt out (currently the only path that opts - // out is legacy mode; every concurrent path provides an error). - if (recoverableError !== null) { - queueHydrationError(recoverableError); - } // This will add the old fiber to the deletion list - - reconcileChildFibers(workInProgress, current.child, null, renderLanes); // We're now not suspended nor dehydrated. - - var nextProps = workInProgress.pendingProps; - var primaryChildren = nextProps.children; - var primaryChildFragment = mountSuspensePrimaryChildren( - workInProgress, - primaryChildren - ); // Needs a placement effect because the parent (the Suspense boundary) already - // mounted but this is a new fiber. - - primaryChildFragment.flags |= Placement; - workInProgress.memoizedState = null; - return primaryChildFragment; -} + var valueCursor = createCursor(null); -function mountSuspenseFallbackAfterRetryWithoutHydrating( - current, - workInProgress, - primaryChildren, - fallbackChildren, - renderLanes -) { - var fiberMode = workInProgress.mode; - var primaryChildProps = { - mode: "visible", - children: primaryChildren - }; - var primaryChildFragment = mountWorkInProgressOffscreenFiber( - primaryChildProps, - fiberMode - ); - var fallbackChildFragment = createFiberFromFragment( - fallbackChildren, - fiberMode, - renderLanes, - null - ); // Needs a placement effect because the parent (the Suspense - // boundary) already mounted but this is a new fiber. - - fallbackChildFragment.flags |= Placement; - primaryChildFragment.return = workInProgress; - fallbackChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; - workInProgress.child = primaryChildFragment; - - if ((workInProgress.mode & ConcurrentMode) !== NoMode) { - // We will have dropped the effect list which contains the - // deletion. We need to reconcile to delete the current child. - reconcileChildFibers(workInProgress, current.child, null, renderLanes); - } - - return fallbackChildFragment; -} + var renderer2CursorDEV; -function updateDehydratedSuspenseComponent( - current, - workInProgress, - didSuspend, - nextProps, - suspenseInstance, - suspenseState, - renderLanes -) { - if (!didSuspend) { - // This is the first render pass. Attempt to hydrate. - pushPrimaryTreeSuspenseHandler(workInProgress); // We should never be hydrating at this point because it is the first pass, - - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - null - ); + { + renderer2CursorDEV = createCursor(null); } - if (isSuspenseInstanceFallback()) { - // This boundary is in a permanent fallback state. In this case, we'll never - // get an update and we'll never be able to hydrate the final content. Let's just try the - // client side render instead. - var digest; - var message, stack; + var rendererSigil; - { - var _getSuspenseInstanceF = getSuspenseInstanceFallbackErrorDetails(); + { + // Use this to detect multiple renderers using the same context + rendererSigil = {}; + } - digest = _getSuspenseInstanceF.digest; - message = _getSuspenseInstanceF.message; - stack = _getSuspenseInstanceF.stack; + var currentlyRenderingFiber = null; + var lastContextDependency = null; + var lastFullyObservedContext = null; + var isDisallowedContextReadInDEV = false; + function resetContextDependencies() { + // This is called right before React yields execution, to ensure `readContext` + // cannot be called outside the render phase. + currentlyRenderingFiber = null; + lastContextDependency = null; + lastFullyObservedContext = null; + + { + isDisallowedContextReadInDEV = false; + } + } + function enterDisallowedContextReadInDEV() { + { + isDisallowedContextReadInDEV = true; + } + } + function exitDisallowedContextReadInDEV() { + { + isDisallowedContextReadInDEV = false; } + } + function pushProvider(providerFiber, context, nextValue) { + { + push(valueCursor, context._currentValue2, providerFiber); + context._currentValue2 = nextValue; - var capturedValue = null; // TODO: Figure out a better signal than encoding a magic digest value. + { + push(renderer2CursorDEV, context._currentRenderer2, providerFiber); - { - var error; + if ( + context._currentRenderer2 !== undefined && + context._currentRenderer2 !== null && + context._currentRenderer2 !== rendererSigil + ) { + error( + "Detected multiple renderers concurrently rendering the " + + "same context provider. This is currently unsupported." + ); + } - if (message) { - // eslint-disable-next-line react-internal/prod-error-codes - error = new Error(message); - } else { - error = new Error( - "The server could not finish this Suspense boundary, likely " + - "due to an error during server rendering. Switched to " + - "client rendering." - ); + context._currentRenderer2 = rendererSigil; + } + } + } + function popProvider(context, providerFiber) { + var currentValue = valueCursor.current; + + { + { + context._currentValue2 = currentValue; } - error.digest = digest; - capturedValue = createCapturedValue(error, digest, stack); + { + var currentRenderer2 = renderer2CursorDEV.current; + pop(renderer2CursorDEV, providerFiber); + context._currentRenderer2 = currentRenderer2; + } } - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - capturedValue - ); + pop(valueCursor, providerFiber); } - - if ( - enableLazyContextPropagation && // TODO: Factoring is a little weird, since we check this right below, too. - // But don't want to re-arrange the if-else chain until/unless this - // feature lands. - !didReceiveUpdate + function scheduleContextWorkOnParentPath( + parent, + renderLanes, + propagationRoot ) { - // We need to check if any children have context before we decide to bail - // out, so propagate the changes now. - lazilyPropagateParentContextChanges(current, workInProgress, renderLanes); - } // We use lanes to indicate that a child might depend on context, so if - // any context has changed, we need to treat is as if the input might have changed. - - var hasContextChanged = includesSomeLane(renderLanes, current.childLanes); + // Update the child lanes of all the ancestors, including the alternates. + var node = parent; - if (didReceiveUpdate || hasContextChanged) { - // This boundary has changed since the first render. This means that we are now unable to - // hydrate it. We might still be able to hydrate it using a higher priority lane. - var root = getWorkInProgressRoot(); + while (node !== null) { + var alternate = node.alternate; - if (root !== null) { - var attemptHydrationAtLane = getBumpedLaneForHydration( - root, - renderLanes - ); + if (!isSubsetOfLanes(node.childLanes, renderLanes)) { + node.childLanes = mergeLanes(node.childLanes, renderLanes); - if ( - attemptHydrationAtLane !== NoLane && - attemptHydrationAtLane !== suspenseState.retryLane + if (alternate !== null) { + alternate.childLanes = mergeLanes( + alternate.childLanes, + renderLanes + ); + } + } else if ( + alternate !== null && + !isSubsetOfLanes(alternate.childLanes, renderLanes) ) { - // Intentionally mutating since this render will get interrupted. This - // is one of the very rare times where we mutate the current tree - // during the render phase. - suspenseState.retryLane = attemptHydrationAtLane; - enqueueConcurrentRenderForLane(current, attemptHydrationAtLane); - scheduleUpdateOnFiber(root, current, attemptHydrationAtLane); // Throw a special object that signals to the work loop that it should - // interrupt the current render. - // - // Because we're inside a React-only execution stack, we don't - // strictly need to throw here — we could instead modify some internal - // work loop state. But using an exception means we don't need to - // check for this case on every iteration of the work loop. So doing - // it this way moves the check out of the fast path. + alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); + } else; - throw SelectiveHydrationException; + if (node === propagationRoot) { + break; } - } // If we did not selectively hydrate, we'll continue rendering without - // hydrating. Mark this tree as suspended to prevent it from committing - // outside a transition. - // - // This path should only happen if the hydration lane already suspended. - // Currently, it also happens during sync updates because there is no - // hydration lane for sync updates. - // TODO: We should ideally have a sync hydration lane that we can apply to do - // a pass where we hydrate this subtree in place using the previous Context and then - // reapply the update afterwards. - - if (isSuspenseInstancePending()); - else { - renderDidSuspendDelayIfPossible(); + + node = node.return; } - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - null - ); - } else if (isSuspenseInstancePending()) { - // This component is still pending more data from the server, so we can't hydrate its - // content. We treat it as if this component suspended itself. It might seem as if - // we could just try to render it client-side instead. However, this will perform a - // lot of unnecessary work and is unlikely to complete since it often will suspend - // on missing data anyway. Additionally, the server might be able to render more - // than we can on the client yet. In that case we'd end up with more fallback states - // on the client than if we just leave it alone. If the server times out or errors - // these should update this boundary to the permanent Fallback state instead. - // Mark it as having captured (i.e. suspended). - workInProgress.flags |= DidCapture; // Leave the child in place. I.e. the dehydrated fragment. - - workInProgress.child = current.child; // Register a callback to retry this boundary once the server has sent the result. - - retryDehydratedSuspenseBoundary.bind(null, current); - registerSuspenseInstanceRetry(); - return null; - } else { - var primaryChildren = nextProps.children; - var primaryChildFragment = mountSuspensePrimaryChildren( - workInProgress, - primaryChildren - ); // Mark the children as hydrating. This is a fast path to know whether this - // tree is part of a hydrating tree. This is used to determine if a child - // node has fully mounted yet, and for scheduling event replaying. - // Conceptually this is similar to Placement in that a new subtree is - // inserted into the React tree here. It just happens to not need DOM - // mutations because it already exists. - - primaryChildFragment.flags |= Hydrating; - return primaryChildFragment; + { + if (node !== propagationRoot) { + 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." + ); + } + } } - } else { - // This is the second render pass. We already attempted to hydrated, but - // something either suspended or errored. - if (workInProgress.flags & ForceClientRender) { - // Something errored during hydration. Try again without hydrating. - pushPrimaryTreeSuspenseHandler(workInProgress); - workInProgress.flags &= ~ForceClientRender; - - var _capturedValue = createCapturedValue( - new Error( - "There was an error while hydrating this Suspense boundary. " + - "Switched to client rendering." - ) - ); - - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - _capturedValue - ); - } else if (workInProgress.memoizedState !== null) { - // Something suspended and we should still be in dehydrated mode. - // Leave the existing child in place. - // Push to avoid a mismatch - pushFallbackTreeSuspenseHandler(workInProgress); - workInProgress.child = current.child; // The dehydrated completion pass expects this flag to be there - // but the normal suspense pass doesn't. - - workInProgress.flags |= DidCapture; - return null; - } else { - // Suspended but we should no longer be in dehydrated mode. - // Therefore we now have to render the fallback. - pushFallbackTreeSuspenseHandler(workInProgress); - var nextPrimaryChildren = nextProps.children; - var nextFallbackChildren = nextProps.fallback; - var fallbackChildFragment = - mountSuspenseFallbackAfterRetryWithoutHydrating( - current, + function propagateContextChange(workInProgress, context, renderLanes) { + if (enableLazyContextPropagation) { + // TODO: This path is only used by Cache components. Update + // lazilyPropagateParentContextChanges to look for Cache components so they + // can take advantage of lazy propagation. + var forcePropagateEntireTree = true; + propagateContextChanges( workInProgress, - nextPrimaryChildren, - nextFallbackChildren, - renderLanes + [context], + renderLanes, + forcePropagateEntireTree ); - var _primaryChildFragment4 = workInProgress.child; - _primaryChildFragment4.memoizedState = - mountSuspenseOffscreenState(renderLanes); - workInProgress.memoizedState = SUSPENDED_MARKER; - return fallbackChildFragment; + } else { + propagateContextChange_eager(workInProgress, context, renderLanes); + } } - } -} - -function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { - fiber.lanes = mergeLanes(fiber.lanes, renderLanes); - var alternate = fiber.alternate; - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, renderLanes); - } + function propagateContextChange_eager( + workInProgress, + context, + renderLanes + ) { + // Only used by eager implementation + if (enableLazyContextPropagation) { + return; + } - scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); -} + var fiber = workInProgress.child; -function propagateSuspenseContextChange( - workInProgress, - firstChild, - renderLanes -) { - // Mark any Suspense boundaries with fallbacks as having work to do. - // If they were previously forced into fallbacks, they may now be able - // to unblock. - var node = firstChild; - - while (node !== null) { - if (node.tag === SuspenseComponent) { - var state = node.memoizedState; - - if (state !== null) { - scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); - } - } else if (node.tag === SuspenseListComponent) { - // If the tail is hidden there might not be an Suspense boundaries - // to schedule work on. In this case we have to schedule it on the - // list itself. - // We don't have to traverse to the children of the list since - // the list will propagate the change when it rerenders. - scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } - - if (node === workInProgress) { - return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow - - while (node.sibling === null) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - if (node.return === null || node.return === workInProgress) { - return; + if (fiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + fiber.return = workInProgress; } - node = node.return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow + while (fiber !== null) { + var nextFiber = void 0; // Visit this fiber. - node.sibling.return = node.return; - node = node.sibling; - } -} + var list = fiber.dependencies; -function findLastContentRow(firstChild) { - // This is going to find the last row among these children that is already - // showing content on the screen, as opposed to being in fallback state or - // new. If a row has multiple Suspense boundaries, any of them being in the - // fallback state, counts as the whole row being in a fallback state. - // Note that the "rows" will be workInProgress, but any nested children - // will still be current since we haven't rendered them yet. The mounted - // order may not be the same as the new order. We use the new order. - var row = firstChild; - var lastContentRow = null; + if (list !== null) { + nextFiber = fiber.child; + var dependency = list.firstContext; - while (row !== null) { - var currentRow = row.alternate; // New rows can't be content rows. + while (dependency !== null) { + // Check if the context matches. + if (dependency.context === context) { + // Match! Schedule an update on this fiber. + if (fiber.tag === ClassComponent) { + // Schedule a force update on the work-in-progress. + var lane = pickArbitraryLane(renderLanes); + var update = createUpdate(lane); + update.tag = ForceUpdate; // TODO: Because we don't have a work-in-progress, this will add the + // update to the current fiber, too, which means it will persist even if + // this render is thrown away. Since it's a race condition, not sure it's + // worth fixing. + // Inlined `enqueueUpdate` to remove interleaved update check - if (currentRow !== null && findFirstSuspended(currentRow) === null) { - lastContentRow = row; - } + var updateQueue = fiber.updateQueue; - row = row.sibling; - } + if (updateQueue === null); + else { + var sharedQueue = updateQueue.shared; + var pending = sharedQueue.pending; - return lastContentRow; -} + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; + } -function validateRevealOrder(revealOrder) { - { - if ( - revealOrder !== undefined && - revealOrder !== "forwards" && - revealOrder !== "backwards" && - revealOrder !== "together" && - !didWarnAboutRevealOrder[revealOrder] - ) { - didWarnAboutRevealOrder[revealOrder] = true; + sharedQueue.pending = update; + } + } - if (typeof revealOrder === "string") { - switch (revealOrder.toLowerCase()) { - case "together": - case "forwards": - case "backwards": { - error( - '"%s" is not a valid value for revealOrder on . ' + - 'Use lowercase "%s" instead.', - revealOrder, - revealOrder.toLowerCase() - ); + fiber.lanes = mergeLanes(fiber.lanes, renderLanes); + var alternate = fiber.alternate; - break; - } + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); + } - case "forward": - case "backward": { - error( - '"%s" is not a valid value for revealOrder on . ' + - 'React uses the -s suffix in the spelling. Use "%ss" instead.', - revealOrder, - revealOrder.toLowerCase() - ); + scheduleContextWorkOnParentPath( + fiber.return, + renderLanes, + workInProgress + ); // Mark the updated lanes on the list, too. - break; - } + list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the + // dependency list. - default: - error( - '"%s" is not a supported revealOrder on . ' + - 'Did you mean "together", "forwards" or "backwards"?', - revealOrder + break; + } + + dependency = dependency.next; + } + } else if (fiber.tag === ContextProvider) { + // Don't scan deeper if this is a matching provider + nextFiber = fiber.type === workInProgress.type ? null : fiber.child; + } else if (fiber.tag === DehydratedFragment) { + // If a dehydrated suspense boundary is in this subtree, we don't know + // if it will have any context consumers in it. The best we can do is + // mark it as having updates. + var parentSuspense = fiber.return; + + if (parentSuspense === null) { + throw new Error( + "We just came from a parent so we must have had a parent. This is a bug in React." ); + } - break; + parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); + var _alternate = parentSuspense.alternate; + + if (_alternate !== null) { + _alternate.lanes = mergeLanes(_alternate.lanes, renderLanes); + } // This is intentionally passing this fiber as the parent + // because we want to schedule this fiber as having work + // on its children. We'll use the childLanes on + // this fiber to indicate that a context has changed. + + scheduleContextWorkOnParentPath( + parentSuspense, + renderLanes, + workInProgress + ); + nextFiber = fiber.sibling; + } else { + // Traverse down. + nextFiber = fiber.child; } - } else { - error( - "%s is not a supported value for revealOrder on . " + - 'Did you mean "together", "forwards" or "backwards"?', - revealOrder - ); + + if (nextFiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + nextFiber.return = fiber; + } else { + // No child. Traverse to next sibling. + nextFiber = fiber; + + while (nextFiber !== null) { + if (nextFiber === workInProgress) { + // We're back to the root of this subtree. Exit. + nextFiber = null; + break; + } + + var sibling = nextFiber.sibling; + + if (sibling !== null) { + // Set the return pointer of the sibling to the work-in-progress fiber. + sibling.return = nextFiber.return; + nextFiber = sibling; + break; + } // No more siblings. Traverse up. + + nextFiber = nextFiber.return; + } + } + + fiber = nextFiber; } } - } -} -function validateTailOptions(tailMode, revealOrder) { - { - if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) { - if (tailMode !== "collapsed" && tailMode !== "hidden") { - didWarnAboutTailOptions[tailMode] = true; + function propagateContextChanges( + workInProgress, + contexts, + renderLanes, + forcePropagateEntireTree + ) { + // Only used by lazy implementation + if (!enableLazyContextPropagation) { + return; + } - error( - '"%s" is not a supported value for tail on . ' + - 'Did you mean "collapsed" or "hidden"?', - tailMode - ); - } else if (revealOrder !== "forwards" && revealOrder !== "backwards") { - didWarnAboutTailOptions[tailMode] = true; + var fiber = workInProgress.child; - error( - ' is only valid if revealOrder is ' + - '"forwards" or "backwards". ' + - 'Did you mean to specify revealOrder="forwards"?', - tailMode - ); + if (fiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + fiber.return = workInProgress; } - } - } -} -function validateSuspenseListNestedChild(childSlot, index) { - { - var isAnArray = isArray(childSlot); - var isIterable = - !isAnArray && typeof getIteratorFn(childSlot) === "function"; - - if (isAnArray || isIterable) { - var type = isAnArray ? "array" : "iterable"; - - error( - "A nested %s was passed to row #%s in . Wrap it in " + - "an additional SuspenseList to configure its revealOrder: " + - " ... " + - "{%s} ... " + - "", - type, - index, - type - ); + while (fiber !== null) { + var nextFiber = void 0; // Visit this fiber. - return false; - } - } + var list = fiber.dependencies; - return true; -} + if (list !== null) { + nextFiber = fiber.child; + var dep = list.firstContext; -function validateSuspenseListChildren(children, revealOrder) { - { - if ( - (revealOrder === "forwards" || revealOrder === "backwards") && - children !== undefined && - children !== null && - children !== false - ) { - if (isArray(children)) { - for (var i = 0; i < children.length; i++) { - if (!validateSuspenseListNestedChild(children[i], i)) { - return; - } - } - } else { - var iteratorFn = getIteratorFn(children); + findChangedDep: while (dep !== null) { + // Assigning these to constants to help Flow + var dependency = dep; + var consumer = fiber; - if (typeof iteratorFn === "function") { - var childrenIterator = iteratorFn.call(children); + for (var i = 0; i < contexts.length; i++) { + var context = contexts[i]; // Check if the context matches. + // TODO: Compare selected values to bail out early. - if (childrenIterator) { - var step = childrenIterator.next(); - var _i = 0; + if (dependency.context === context) { + // Match! Schedule an update on this fiber. + // In the lazy implementation, don't mark a dirty flag on the + // dependency itself. Not all changes are propagated, so we can't + // rely on the propagation function alone to determine whether + // something has changed; the consumer will check. In the future, we + // could add back a dirty flag as an optimization to avoid double + // checking, but until we have selectors it's not really worth + // the trouble. + consumer.lanes = mergeLanes(consumer.lanes, renderLanes); + var alternate = consumer.alternate; - for (; !step.done; step = childrenIterator.next()) { - if (!validateSuspenseListNestedChild(step.value, _i)) { - return; - } + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); + } - _i++; + scheduleContextWorkOnParentPath( + consumer.return, + renderLanes, + workInProgress + ); + + if (!forcePropagateEntireTree) { + // During lazy propagation, when we find a match, we can defer + // propagating changes to the children, because we're going to + // visit them during render. We should continue propagating the + // siblings, though + nextFiber = null; + } // Since we already found a match, we can stop traversing the + // dependency list. + + break findChangedDep; + } } + + dep = dependency.next; } - } else { - error( - 'A single row was passed to a . ' + - "This is not useful since it needs multiple rows. " + - "Did you mean to pass multiple children or an array?", - revealOrder + } else if (fiber.tag === DehydratedFragment) { + // If a dehydrated suspense boundary is in this subtree, we don't know + // if it will have any context consumers in it. The best we can do is + // mark it as having updates. + var parentSuspense = fiber.return; + + if (parentSuspense === null) { + throw new Error( + "We just came from a parent so we must have had a parent. This is a bug in React." + ); + } + + parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); + var _alternate2 = parentSuspense.alternate; + + if (_alternate2 !== null) { + _alternate2.lanes = mergeLanes(_alternate2.lanes, renderLanes); + } // This is intentionally passing this fiber as the parent + // because we want to schedule this fiber as having work + // on its children. We'll use the childLanes on + // this fiber to indicate that a context has changed. + + scheduleContextWorkOnParentPath( + parentSuspense, + renderLanes, + workInProgress ); + nextFiber = null; + } else { + // Traverse down. + nextFiber = fiber.child; + } + + if (nextFiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + nextFiber.return = fiber; + } else { + // No child. Traverse to next sibling. + nextFiber = fiber; + + while (nextFiber !== null) { + if (nextFiber === workInProgress) { + // We're back to the root of this subtree. Exit. + nextFiber = null; + break; + } + + var sibling = nextFiber.sibling; + + if (sibling !== null) { + // Set the return pointer of the sibling to the work-in-progress fiber. + sibling.return = nextFiber.return; + nextFiber = sibling; + break; + } // No more siblings. Traverse up. + + nextFiber = nextFiber.return; + } } + + fiber = nextFiber; } } - } -} -function initSuspenseListRenderState( - workInProgress, - isBackwards, - tail, - lastContentRow, - tailMode -) { - var renderState = workInProgress.memoizedState; - - if (renderState === null) { - workInProgress.memoizedState = { - isBackwards: isBackwards, - rendering: null, - renderingStartTime: 0, - last: lastContentRow, - tail: tail, - tailMode: tailMode - }; - } else { - // We can reuse the existing object from previous renders. - renderState.isBackwards = isBackwards; - renderState.rendering = null; - renderState.renderingStartTime = 0; - renderState.last = lastContentRow; - renderState.tail = tail; - renderState.tailMode = tailMode; - } -} // This can end up rendering this component multiple passes. -// The first pass splits the children fibers into two sets. A head and tail. -// We first render the head. If anything is in fallback state, we do another -// pass through beginWork to rerender all children (including the tail) with -// the force suspend context. If the first render didn't have anything in -// in fallback state. Then we render each row in the tail one-by-one. -// That happens in the completeWork phase without going back to beginWork. - -function updateSuspenseListComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; - var revealOrder = nextProps.revealOrder; - var tailMode = nextProps.tail; - var newChildren = nextProps.children; - validateRevealOrder(revealOrder); - validateTailOptions(tailMode, revealOrder); - validateSuspenseListChildren(newChildren, revealOrder); - reconcileChildren(current, workInProgress, newChildren, renderLanes); - var suspenseContext = suspenseStackCursor.current; - var shouldForceFallback = hasSuspenseListContext( - suspenseContext, - ForceSuspenseFallback - ); - - if (shouldForceFallback) { - suspenseContext = setShallowSuspenseListContext( - suspenseContext, - ForceSuspenseFallback - ); - workInProgress.flags |= DidCapture; - } else { - var didSuspendBefore = - current !== null && (current.flags & DidCapture) !== NoFlags$1; - - if (didSuspendBefore) { - // If we previously forced a fallback, we need to schedule work - // on any nested boundaries to let them know to try to render - // again. This is the same as context updating. - propagateSuspenseContextChange( + function lazilyPropagateParentContextChanges( + current, + workInProgress, + renderLanes + ) { + var forcePropagateEntireTree = false; + propagateParentContextChanges( + current, workInProgress, - workInProgress.child, - renderLanes + renderLanes, + forcePropagateEntireTree ); - } - - suspenseContext = setDefaultShallowSuspenseListContext(suspenseContext); - } + } // Used for propagating a deferred tree (Suspense, Offscreen). We must propagate + // to the entire subtree, because we won't revisit it until after the current + // render has completed, at which point we'll have lost track of which providers + // have changed. - pushSuspenseListContext(workInProgress, suspenseContext); - - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - // In legacy mode, SuspenseList doesn't work so we just - // use make it a noop by treating it as the default revealOrder. - workInProgress.memoizedState = null; - } else { - switch (revealOrder) { - case "forwards": { - var lastContentRow = findLastContentRow(workInProgress.child); - var tail; + function propagateParentContextChangesToDeferredTree( + current, + workInProgress, + renderLanes + ) { + var forcePropagateEntireTree = true; + propagateParentContextChanges( + current, + workInProgress, + renderLanes, + forcePropagateEntireTree + ); + } - if (lastContentRow === null) { - // The whole list is part of the tail. - // TODO: We could fast path by just rendering the tail now. - tail = workInProgress.child; - workInProgress.child = null; - } else { - // Disconnect the tail rows after the content row. - // We're going to render them separately later. - tail = lastContentRow.sibling; - lastContentRow.sibling = null; + function propagateParentContextChanges( + current, + workInProgress, + renderLanes, + forcePropagateEntireTree + ) { + if (!enableLazyContextPropagation) { + return; + } // Collect all the parent providers that changed. Since this is usually small + // number, we use an Array instead of Set. + + var contexts = null; + var parent = workInProgress; + var isInsidePropagationBailout = false; + + while (parent !== null) { + if (!isInsidePropagationBailout) { + if ((parent.flags & NeedsPropagation) !== NoFlags$1) { + isInsidePropagationBailout = true; + } else if ((parent.flags & DidPropagateContext) !== NoFlags$1) { + break; + } } - initSuspenseListRenderState( - workInProgress, - false, // isBackwards - tail, - lastContentRow, - tailMode - ); - break; - } + if (parent.tag === ContextProvider) { + var currentParent = parent.alternate; + + if (currentParent === null) { + throw new Error( + "Should have a current fiber. This is a bug in React." + ); + } - case "backwards": { - // We're going to find the first row that has existing content. - // At the same time we're going to reverse the list of everything - // we pass in the meantime. That's going to be our tail in reverse - // order. - var _tail = null; - var row = workInProgress.child; - workInProgress.child = null; + var oldProps = currentParent.memoizedProps; - while (row !== null) { - var currentRow = row.alternate; // New rows can't be content rows. + if (oldProps !== null) { + var providerType = parent.type; + var context = providerType._context; + var newProps = parent.pendingProps; + var newValue = newProps.value; + var oldValue = oldProps.value; - if (currentRow !== null && findFirstSuspended(currentRow) === null) { - // This is the beginning of the main content. - workInProgress.child = row; - break; + if (!objectIs(newValue, oldValue)) { + if (contexts !== null) { + contexts.push(context); + } else { + contexts = [context]; + } + } } + } - var nextRow = row.sibling; - row.sibling = _tail; - _tail = row; - row = nextRow; - } // TODO: If workInProgress.child is null, we can continue on the tail immediately. - - initSuspenseListRenderState( - workInProgress, - true, // isBackwards - _tail, - null, // last - tailMode - ); - break; + parent = parent.return; } - case "together": { - initSuspenseListRenderState( + if (contexts !== null) { + // If there were any changed providers, search through the children and + // propagate their changes. + propagateContextChanges( workInProgress, - false, // isBackwards - null, // tail - null, // last - undefined + contexts, + renderLanes, + forcePropagateEntireTree ); - break; - } + } // This is an optimization so that we only propagate once per subtree. If a + // deeply nested child bails out, and it calls this propagation function, it + // uses this flag to know that the remaining ancestor providers have already + // been propagated. + // + // NOTE: This optimization is only necessary because we sometimes enter the + // begin phase of nodes that don't have any work scheduled on them — + // specifically, the siblings of a node that _does_ have scheduled work. The + // siblings will bail out and call this function again, even though we already + // propagated content changes to it and its subtree. So we use this flag to + // mark that the parent providers already propagated. + // + // Unfortunately, though, we need to ignore this flag when we're inside a + // tree whose context propagation was deferred — that's what the + // `NeedsPropagation` flag is for. + // + // If we could instead bail out before entering the siblings' begin phase, + // then we could remove both `DidPropagateContext` and `NeedsPropagation`. + // Consider this as part of the next refactor to the fiber tree structure. - default: { - // The default reveal order is the same as not having - // a boundary. - workInProgress.memoizedState = null; - } + workInProgress.flags |= DidPropagateContext; } - } - - return workInProgress.child; -} - -function updatePortalComponent(current, workInProgress, renderLanes) { - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - var nextChildren = workInProgress.pendingProps; - - if (current === null) { - // Portals are special because we don't append the children during mount - // but at commit. Therefore we need to track insertions which the normal - // flow doesn't do during mount. This doesn't happen at the root because - // the root always starts with a "current" with a null child. - // TODO: Consider unifying this with how the root works. - workInProgress.child = reconcileChildFibers( - workInProgress, - null, - nextChildren, - renderLanes - ); - } else { - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - } - return workInProgress.child; -} + function checkIfContextChanged(currentDependencies) { + if (!enableLazyContextPropagation) { + return false; + } // Iterate over the current dependencies to see if something changed. This + // only gets called if props and state has already bailed out, so it's a + // relatively uncommon path, except at the root of a changed subtree. + // Alternatively, we could move these comparisons into `readContext`, but + // that's a much hotter path, so I think this is an appropriate trade off. -var hasWarnedAboutUsingNoValuePropOnContextProvider = false; + var dependency = currentDependencies.firstContext; -function updateContextProvider(current, workInProgress, renderLanes) { - var providerType = workInProgress.type; - var context = providerType._context; - var newProps = workInProgress.pendingProps; - var oldProps = workInProgress.memoizedProps; - var newValue = newProps.value; + while (dependency !== null) { + var context = dependency.context; + var newValue = context._currentValue2; + var oldValue = dependency.memoizedValue; - { - if (!("value" in newProps)) { - if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { - hasWarnedAboutUsingNoValuePropOnContextProvider = true; + if (!objectIs(newValue, oldValue)) { + return true; + } - error( - "The `value` prop is required for the ``. Did you misspell it or forget to pass it?" - ); + dependency = dependency.next; } - } - var providerPropTypes = workInProgress.type.propTypes; - - if (providerPropTypes) { - checkPropTypes(providerPropTypes, newProps, "prop", "Context.Provider"); + return false; } - } + function prepareToReadContext(workInProgress, renderLanes) { + currentlyRenderingFiber = workInProgress; + lastContextDependency = null; + lastFullyObservedContext = null; + var dependencies = workInProgress.dependencies; - pushProvider(workInProgress, context, newValue); + if (dependencies !== null) { + if (enableLazyContextPropagation) { + // Reset the work-in-progress list + dependencies.firstContext = null; + } else { + var firstContext = dependencies.firstContext; - if (enableLazyContextPropagation); - else { - if (oldProps !== null) { - var oldValue = oldProps.value; + if (firstContext !== null) { + if (includesSomeLane(dependencies.lanes, renderLanes)) { + // Context list has a pending update. Mark that this fiber performed work. + markWorkInProgressReceivedUpdate(); + } // Reset the work-in-progress list - if (objectIs(oldValue, newValue)) { - // No change. Bailout early if children are the same. - if (oldProps.children === newProps.children && !hasContextChanged()) { - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - ); + dependencies.firstContext = null; + } } - } else { - // The context value changed. Search for matching consumers and schedule - // them to update. - propagateContextChange(workInProgress, context, renderLanes); } } - } - - var newChildren = newProps.children; - reconcileChildren(current, workInProgress, newChildren, renderLanes); - return workInProgress.child; -} - -var hasWarnedAboutUsingContextAsConsumer = false; - -function updateContextConsumer(current, workInProgress, renderLanes) { - var context = workInProgress.type; // The logic below for Context differs depending on PROD or DEV mode. In - // DEV mode, we create a separate object for Context.Consumer that acts - // like a proxy to Context. This proxy object adds unnecessary code in PROD - // so we use the old behaviour (Context.Consumer references Context) to - // reduce size and overhead. The separate object references context via - // a property called "_context", which also gives us the ability to check - // in DEV mode if this property exists or not and warn if it does not. - - { - if (context._context === undefined) { - // This may be because it's a Context (rather than a Consumer). - // Or it may be because it's older React where they're the same thing. - // We only want to warn if we're sure it's a new React. - if (context !== context.Consumer) { - if (!hasWarnedAboutUsingContextAsConsumer) { - hasWarnedAboutUsingContextAsConsumer = true; - + function readContext(context) { + { + // This warning would fire if you read context inside a Hook like useMemo. + // Unlike the class check below, it's not enforced in production for perf. + if (isDisallowedContextReadInDEV) { error( - "Rendering directly is not supported and will be removed in " + - "a future major release. Did you mean to render instead?" + "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()." ); } } - } else { - context = context._context; - } - } - var newProps = workInProgress.pendingProps; - var render = newProps.children; + return readContextForConsumer(currentlyRenderingFiber, context); + } + function readContextDuringReconcilation(consumer, context, renderLanes) { + if (currentlyRenderingFiber === null) { + prepareToReadContext(consumer, renderLanes); + } - { - if (typeof render !== "function") { - 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." - ); + return readContextForConsumer(consumer, context); } - } - prepareToReadContext(workInProgress, renderLanes); - var newValue = readContext(context); + function readContextForConsumer(consumer, context) { + var value = context._currentValue2; - if (enableSchedulingProfiler) { - markComponentRenderStarted(workInProgress); - } + if (lastFullyObservedContext === context); + else { + var contextItem = { + context: context, + memoizedValue: value, + next: null + }; - var newChildren; + if (lastContextDependency === null) { + if (consumer === null) { + 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()." + ); + } // This is the first dependency for this component. Create a new list. - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - newChildren = render(newValue); - setIsRendering(false); - } + lastContextDependency = contextItem; + consumer.dependencies = { + lanes: NoLanes, + firstContext: contextItem + }; - if (enableSchedulingProfiler) { - markComponentRenderStopped(); - } // React DevTools reads this flag. + if (enableLazyContextPropagation) { + consumer.flags |= NeedsPropagation; + } + } else { + // Append a new context item. + lastContextDependency = lastContextDependency.next = contextItem; + } + } - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, newChildren, renderLanes); - return workInProgress.child; -} + return value; + } -function updateScopeComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; - var nextChildren = nextProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + // replace it with a lightweight shim that only has the features we use. -function markWorkInProgressReceivedUpdate() { - didReceiveUpdate = true; -} -function checkIfWorkInProgressReceivedUpdate() { - return didReceiveUpdate; -} + var AbortControllerLocal = + typeof AbortController !== "undefined" + ? AbortController // $FlowFixMe[missing-this-annot] + : // $FlowFixMe[prop-missing] + function AbortControllerShim() { + var listeners = []; + var signal = (this.signal = { + aborted: false, + addEventListener: function (type, listener) { + listeners.push(listener); + } + }); -function resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress) { - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - if (current !== null) { - // A lazy component only mounts if it suspended inside a non- - // concurrent tree, in an inconsistent state. We want to treat it like - // a new mount, even though an empty version of it already committed. - // Disconnect the alternate pointers. - current.alternate = null; - workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect + this.abort = function () { + signal.aborted = true; + listeners.forEach(function (listener) { + return listener(); + }); + }; + }; // Intentionally not named imports because Rollup would + // use dynamic dispatch for CommonJS interop named imports. + + var scheduleCallback$1 = Scheduler.unstable_scheduleCallback, + NormalPriority = Scheduler.unstable_NormalPriority; + var CacheContext = { + $$typeof: REACT_CONTEXT_TYPE, + // We don't use Consumer/Provider for Cache components. So we'll cheat. + Consumer: null, + Provider: null, + // We'll initialize these at the root. + _currentValue: null, + _currentValue2: null, + _threadCount: 0, + _defaultValue: null, + _globalName: null + }; - workInProgress.flags |= Placement; + { + CacheContext._currentRenderer = null; + CacheContext._currentRenderer2 = null; + } // Creates a new empty Cache instance with a ref-count of 0. The caller is responsible + // for retaining the cache once it is in use (retainCache), and releasing the cache + // once it is no longer needed (releaseCache). + + function createCache() { + var cache = { + controller: new AbortControllerLocal(), + data: new Map(), + refCount: 0 + }; + return cache; } - } -} - -function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { - if (current !== null) { - // Reuse previous dependencies - workInProgress.dependencies = current.dependencies; - } + function retainCache(cache) { + { + if (cache.controller.signal.aborted) { + warn( + "A cache instance was retained after it was already freed. " + + "This likely indicates a bug in React." + ); + } + } - { - // Don't update "base" render times for bailouts. - stopProfilerTimerIfRunning(); - } + cache.refCount++; + } // Cleanup a cache instance, potentially freeing it if there are no more references - markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. + function releaseCache(cache) { + cache.refCount--; - if (!includesSomeLane(renderLanes, workInProgress.childLanes)) { - // The children don't have any work either. We can skip them. - // TODO: Once we add back resuming, we should check if the children are - // a work-in-progress set. If so, we need to transfer their effects. - if (enableLazyContextPropagation && current !== null) { - // Before bailing out, check if there are any context changes in - // the children. - lazilyPropagateParentContextChanges(current, workInProgress, renderLanes); + { + if (cache.refCount < 0) { + warn( + "A cache instance was released after it was already freed. " + + "This likely indicates a bug in React." + ); + } + } - if (!includesSomeLane(renderLanes, workInProgress.childLanes)) { - return null; + if (cache.refCount === 0) { + scheduleCallback$1(NormalPriority, function () { + cache.controller.abort(); + }); } - } else { - return null; } - } // This fiber doesn't have work, but its subtree does. Clone the child - // fibers and continue. - - cloneChildFibers(current, workInProgress); - return workInProgress.child; -} - -function remountFiber(current, oldWorkInProgress, newWorkInProgress) { - { - var returnFiber = oldWorkInProgress.return; + function pushCacheProvider(workInProgress, cache) { + pushProvider(workInProgress, CacheContext, cache); + } + function popCacheProvider(workInProgress, cache) { + popProvider(CacheContext, workInProgress); + } - if (returnFiber === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Cannot swap the root fiber."); - } // Disconnect from the old current. - // It will get deleted. + var ReactCurrentBatchConfig$1 = + ReactSharedInternals.ReactCurrentBatchConfig; + var NoTransition = null; + function requestCurrentTransition() { + return ReactCurrentBatchConfig$1.transition; + } // When retrying a Suspense/Offscreen boundary, we restore the cache that was + // used during the previous render by placing it here, on the stack. - current.alternate = null; - oldWorkInProgress.alternate = null; // Connect to the new tree. + var resumedCache = createCursor(null); // During the render/synchronous commit phase, we don't actually process the + // transitions. Therefore, we want to lazily combine transitions. Instead of + // comparing the arrays of transitions when we combine them and storing them + // and filtering out the duplicates, we will instead store the unprocessed transitions + // in an array and actually filter them in the passive phase. - newWorkInProgress.index = oldWorkInProgress.index; - newWorkInProgress.sibling = oldWorkInProgress.sibling; - newWorkInProgress.return = oldWorkInProgress.return; - newWorkInProgress.ref = oldWorkInProgress.ref; // Replace the child/sibling pointers above it. + var transitionStack = createCursor(null); - if (oldWorkInProgress === returnFiber.child) { - returnFiber.child = newWorkInProgress; - } else { - var prevSibling = returnFiber.child; + function peekCacheFromPool() { + // If we're rendering inside a Suspense boundary that is currently hidden, + // we should use the same cache that we used during the previous render, if + // one exists. - if (prevSibling === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Expected parent to have a child."); - } // $FlowFixMe[incompatible-use] found when upgrading Flow + var cacheResumedFromPreviousRender = resumedCache.current; - while (prevSibling.sibling !== oldWorkInProgress) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - prevSibling = prevSibling.sibling; + if (cacheResumedFromPreviousRender !== null) { + return cacheResumedFromPreviousRender; + } // Otherwise, check the root's cache pool. - if (prevSibling === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Expected to find the previous sibling."); - } - } // $FlowFixMe[incompatible-use] found when upgrading Flow + var root = getWorkInProgressRoot(); + var cacheFromRootCachePool = root.pooledCache; + return cacheFromRootCachePool; + } + + function requestCacheFromPool(renderLanes) { + // Similar to previous function, except if there's not already a cache in the + // pool, we allocate a new one. + var cacheFromPool = peekCacheFromPool(); + + if (cacheFromPool !== null) { + return cacheFromPool; + } // Create a fresh cache and add it to the root cache pool. A cache can have + // multiple owners: + // - A cache pool that lives on the FiberRoot. This is where all fresh caches + // are originally created (TODO: except during refreshes, until we implement + // this correctly). The root takes ownership immediately when the cache is + // created. Conceptually, root.pooledCache is an Option> (owned), + // and the return value of this function is a &Arc (borrowed). + // - One of several fiber types: host root, cache boundary, suspense + // component. These retain and release in the commit phase. - prevSibling.sibling = newWorkInProgress; - } // Delete the old fiber and place the new one. - // Since the old fiber is disconnected, we have to schedule it manually. + var root = getWorkInProgressRoot(); + var freshCache = createCache(); + root.pooledCache = freshCache; + retainCache(freshCache); - var deletions = returnFiber.deletions; + if (freshCache !== null) { + root.pooledCacheLanes |= renderLanes; + } - if (deletions === null) { - returnFiber.deletions = [current]; - returnFiber.flags |= ChildDeletion; - } else { - deletions.push(current); + return freshCache; } - - newWorkInProgress.flags |= Placement; // Restart work from the new fiber. - - return newWorkInProgress; - } -} - -function checkScheduledUpdateOrContext(current, renderLanes) { - // Before performing an early bailout, we must check if there are pending - // updates or context. - var updateLanes = current.lanes; - - if (includesSomeLane(updateLanes, renderLanes)) { - return true; - } // No pending update, but because context is propagated lazily, we need - // to check for a context change before we bail out. - - if (enableLazyContextPropagation) { - var dependencies = current.dependencies; - - if (dependencies !== null && checkIfContextChanged(dependencies)) { - return true; + function pushRootTransition(workInProgress, root, renderLanes) { + if (enableTransitionTracing) { + var rootTransitions = getWorkInProgressTransitions(); + push(transitionStack, rootTransitions, workInProgress); + } } - } - - return false; -} - -function attemptEarlyBailoutIfNoScheduledUpdate( - current, - workInProgress, - renderLanes -) { - // This fiber does not have any pending work. Bailout without entering - // the begin phase. There's still some bookkeeping we that needs to be done - // in this optimized path, mostly pushing stuff onto the stack. - switch (workInProgress.tag) { - case HostRoot: - pushHostRootContext(workInProgress); - pushRootTransition(workInProgress); + function popRootTransition(workInProgress, root, renderLanes) { + if (enableTransitionTracing) { + pop(transitionStack, workInProgress); + } + } + function pushTransition( + offscreenWorkInProgress, + prevCachePool, + newTransitions + ) { + { + if (prevCachePool === null) { + push(resumedCache, resumedCache.current, offscreenWorkInProgress); + } else { + push(resumedCache, prevCachePool.pool, offscreenWorkInProgress); + } + } if (enableTransitionTracing) { - pushRootMarkerInstance(workInProgress); + if (transitionStack.current === null) { + push(transitionStack, newTransitions, offscreenWorkInProgress); + } else if (newTransitions === null) { + push( + transitionStack, + transitionStack.current, + offscreenWorkInProgress + ); + } else { + push( + transitionStack, + transitionStack.current.concat(newTransitions), + offscreenWorkInProgress + ); + } } + } + function popTransition(workInProgress, current) { + if (current !== null) { + if (enableTransitionTracing) { + pop(transitionStack, workInProgress); + } - { - var cache = current.memoizedState.cache; - pushCacheProvider(workInProgress, cache); + { + pop(resumedCache, workInProgress); + } + } + } + function getPendingTransitions() { + if (!enableTransitionTracing) { + return null; } - break; - case HostSingleton: - case HostComponent: - pushHostContext(workInProgress); - break; + return transitionStack.current; + } + function getSuspendedCache() { + // cache that would have been used to render fresh data during this render, + // if there was any, so that we can resume rendering with the same cache when + // we receive more data. - case ClassComponent: { - var Component = workInProgress.type; + var cacheFromPool = peekCacheFromPool(); - if (isContextProvider(Component)) { - pushContextProvider(workInProgress); + if (cacheFromPool === null) { + return null; } - break; + return { + // We must also save the parent, so that when we resume we can detect + // a refresh. + parent: CacheContext._currentValue2, + pool: cacheFromPool + }; } + function getOffscreenDeferredCache() { + var cacheFromPool = peekCacheFromPool(); - case HostPortal: - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - break; + if (cacheFromPool === null) { + return null; + } - case ContextProvider: { - var newValue = workInProgress.memoizedProps.value; - var context = workInProgress.type._context; - pushProvider(workInProgress, context, newValue); - break; + return { + // We must also store the parent, so that when we resume we can detect + // a refresh. + parent: CacheContext._currentValue2, + pool: cacheFromPool + }; + } + + function getSuspenseFallbackChild(fiber) { + return fiber.child.sibling.child; } - case Profiler: + var emptyObject = {}; + + function collectScopedNodes(node, fn, scopedNodes) { { - // Profiler should only call onRender when one of its descendants actually rendered. - var hasChildWork = includesSomeLane( - renderLanes, - workInProgress.childLanes - ); + if (node.tag === HostComponent) { + var type = node.type, + memoizedProps = node.memoizedProps, + stateNode = node.stateNode; + var instance = getPublicInstance(stateNode); - if (hasChildWork) { - workInProgress.flags |= Update; + if ( + instance !== null && + fn(type, memoizedProps || emptyObject, instance) === true + ) { + scopedNodes.push(instance); + } } - { - // Reset effect durations for the next eventual effect phase. - // These are reset during render to allow the DevTools commit hook a chance to read them, - var stateNode = workInProgress.stateNode; - stateNode.effectDuration = 0; - stateNode.passiveEffectDuration = 0; + var child = node.child; + + if (isFiberSuspenseAndTimedOut(node)) { + child = getSuspenseFallbackChild(node); + } + + if (child !== null) { + collectScopedNodesFromChildren(child, fn, scopedNodes); } } + } - break; + function collectFirstScopedNode(node, fn) { + { + if (node.tag === HostComponent) { + var type = node.type, + memoizedProps = node.memoizedProps, + stateNode = node.stateNode; + var instance = getPublicInstance(stateNode); + + if (instance !== null && fn(type, memoizedProps, instance) === true) { + return instance; + } + } - case SuspenseComponent: { - var state = workInProgress.memoizedState; + var child = node.child; - if (state !== null) { - if (state.dehydrated !== null) { - // We're not going to render the children, so this is just to maintain - // push/pop symmetry - pushPrimaryTreeSuspenseHandler(workInProgress); // We know that this component will suspend again because if it has - // been unsuspended it has committed as a resolved Suspense component. - // If it needs to be retried, it should have work scheduled on it. + if (isFiberSuspenseAndTimedOut(node)) { + child = getSuspenseFallbackChild(node); + } - workInProgress.flags |= DidCapture; // We should never render the children of a dehydrated boundary until we - // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork. + if (child !== null) { + return collectFirstScopedNodeFromChildren(child, fn); + } + } - return null; - } // If this boundary is currently timed out, we need to decide - // whether to retry the primary children, or to skip over it and - // go straight to the fallback. Check the priority of the primary - // child fragment. + return null; + } - var primaryChildFragment = workInProgress.child; - var primaryChildLanes = primaryChildFragment.childLanes; + function collectScopedNodesFromChildren(startingChild, fn, scopedNodes) { + var child = startingChild; - if (includesSomeLane(renderLanes, primaryChildLanes)) { - // The primary children have pending work. Use the normal path - // to attempt to render the primary children again. - return updateSuspenseComponent(current, workInProgress, renderLanes); - } else { - // The primary child fragment does not have pending work marked - // on it - pushPrimaryTreeSuspenseHandler(workInProgress); // The primary children do not have pending work with sufficient - // priority. Bailout. + while (child !== null) { + collectScopedNodes(child, fn, scopedNodes); + child = child.sibling; + } + } - var child = bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - ); + function collectFirstScopedNodeFromChildren(startingChild, fn) { + var child = startingChild; - if (child !== null) { - // The fallback children have pending work. Skip over the - // primary children and work on the fallback. - return child.sibling; - } else { - // Note: We can return `null` here because we already checked - // whether there were nested context consumers, via the call to - // `bailoutOnAlreadyFinishedWork` above. - return null; - } + while (child !== null) { + var scopedNode = collectFirstScopedNode(child, fn); + + if (scopedNode !== null) { + return scopedNode; } - } else { - pushPrimaryTreeSuspenseHandler(workInProgress); + + child = child.sibling; } - break; + return null; } - case SuspenseListComponent: { - var didSuspendBefore = (current.flags & DidCapture) !== NoFlags$1; + function collectNearestContextValues(node, context, childContextValues) { + if (node.tag === ContextProvider && node.type._context === context) { + var contextValue = node.memoizedProps.value; + childContextValues.push(contextValue); + } else { + var child = node.child; - var _hasChildWork = includesSomeLane( - renderLanes, - workInProgress.childLanes - ); + if (isFiberSuspenseAndTimedOut(node)) { + child = getSuspenseFallbackChild(node); + } - if (enableLazyContextPropagation && !_hasChildWork) { - // Context changes may not have been propagated yet. We need to do - // that now, before we can decide whether to bail out. - // TODO: We use `childLanes` as a heuristic for whether there is - // remaining work in a few places, including - // `bailoutOnAlreadyFinishedWork` and - // `updateDehydratedSuspenseComponent`. We should maybe extract this - // into a dedicated function. - lazilyPropagateParentContextChanges( - current, - workInProgress, - renderLanes - ); - _hasChildWork = includesSomeLane( - renderLanes, - workInProgress.childLanes - ); + if (child !== null) { + collectNearestChildContextValues(child, context, childContextValues); + } } + } - if (didSuspendBefore) { - if (_hasChildWork) { - // If something was in fallback state last time, and we have all the - // same children then we're still in progressive loading state. - // Something might get unblocked by state updates or retries in the - // tree which will affect the tail. So we need to use the normal - // path to compute the correct tail. - return updateSuspenseListComponent( - current, - workInProgress, - renderLanes - ); - } // If none of the children had any work, that means that none of - // them got retried so they'll still be blocked in the same way - // as before. We can fast bail out. - - workInProgress.flags |= DidCapture; - } // If nothing suspended before and we're rendering the same children, - // then the tail doesn't matter. Anything new that suspends will work - // in the "together" mode, so we can continue from the state we had. - - var renderState = workInProgress.memoizedState; + function collectNearestChildContextValues( + startingChild, + context, + childContextValues + ) { + var child = startingChild; - if (renderState !== null) { - // Reset to the "together" mode in case we've started a different - // update in the past but didn't complete it. - renderState.rendering = null; - renderState.tail = null; - renderState.lastEffect = null; + while (child !== null) { + collectNearestContextValues(child, context, childContextValues); + child = child.sibling; } + } - pushSuspenseListContext(workInProgress, suspenseStackCursor.current); + function DO_NOT_USE_queryAllNodes(fn) { + var currentFiber = getInstanceFromScope(); - if (_hasChildWork) { - break; - } else { - // If none of the children had any work, that means that none of - // them got retried so they'll still be blocked in the same way - // as before. We can fast bail out. + if (currentFiber === null) { return null; } - } - case OffscreenComponent: - case LegacyHiddenComponent: { - // Need to check if the tree still needs to be deferred. This is - // almost identical to the logic used in the normal update path, - // so we'll just enter that. The only difference is we'll bail out - // at the next level instead of this one, because the child props - // have not changed. Which is fine. - // TODO: Probably should refactor `beginWork` to split the bailout - // path from the normal path. I'm tempted to do a labeled break here - // but I won't :) - workInProgress.lanes = NoLanes; - return updateOffscreenComponent(current, workInProgress, renderLanes); - } + var child = currentFiber.child; + var scopedNodes = []; - case CacheComponent: { - { - var _cache = current.memoizedState.cache; - pushCacheProvider(workInProgress, _cache); + if (child !== null) { + collectScopedNodesFromChildren(child, fn, scopedNodes); } - break; + return scopedNodes.length === 0 ? null : scopedNodes; } - case TracingMarkerComponent: { - if (enableTransitionTracing) { - var instance = workInProgress.stateNode; + function DO_NOT_USE_queryFirstNode(fn) { + var currentFiber = getInstanceFromScope(); - if (instance !== null) { - pushMarkerInstance(workInProgress, instance); - } + if (currentFiber === null) { + return null; } - } - } - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); -} + var child = currentFiber.child; -function beginWork$1(current, workInProgress, renderLanes) { - { - if (workInProgress._debugNeedsRemount && current !== null) { - // This will restart the begin phase with a new fiber. - return remountFiber( - current, - workInProgress, - createFiberFromTypeAndProps( - workInProgress.type, - workInProgress.key, - workInProgress.pendingProps, - workInProgress._debugSource || null, - workInProgress._debugOwner || null, - workInProgress.mode, - workInProgress.lanes - ) - ); + if (child !== null) { + return collectFirstScopedNodeFromChildren(child, fn); + } + + return null; } - } - if (current !== null) { - var oldProps = current.memoizedProps; - var newProps = workInProgress.pendingProps; + function containsNode(node) { + var fiber = getInstanceFromNode(); - if ( - oldProps !== newProps || - hasContextChanged() || // Force a re-render if the implementation changed due to hot reload: - workInProgress.type !== current.type - ) { - // If props or context changed, mark the fiber as having performed work. - // This may be unset if the props are determined to be equal later (memo). - didReceiveUpdate = true; - } else { - // Neither props nor legacy context changes. Check if there's a pending - // update or context change. - var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( - current, - renderLanes - ); + while (fiber !== null) { + if (fiber.tag === ScopeComponent && fiber.stateNode === this) { + return true; + } - if ( - !hasScheduledUpdateOrContext && // If this is the second pass of an error or suspense boundary, there - // may not be work scheduled on `current`, so we check for this flag. - (workInProgress.flags & DidCapture) === NoFlags$1 - ) { - // No pending updates or context. Bail out now. - didReceiveUpdate = false; - return attemptEarlyBailoutIfNoScheduledUpdate( - current, - workInProgress, - renderLanes - ); + fiber = fiber.return; } - if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags$1) { - // This is a special case that only exists for legacy mode. - // See https://github.com/facebook/react/pull/19216. - didReceiveUpdate = true; - } else { - // An update was scheduled on this fiber, but there are no new props - // nor legacy context. Set this to false. If an update queue or context - // consumer produces a changed value, it will set this to true. Otherwise, - // the component will assume the children have not changed and bail out. - didReceiveUpdate = false; - } + return false; } - } else { - didReceiveUpdate = false; - } // Before entering the begin phase, clear pending update priority. - // TODO: This assumes that we're about to evaluate the component and process - // the update queue. However, there's an exception: SimpleMemoComponent - // sometimes bails out later in the begin phase. This indicates that we should - // move this assignment out of the common path and into each branch. - workInProgress.lanes = NoLanes; + function getChildContextValues(context) { + var currentFiber = getInstanceFromScope(); - switch (workInProgress.tag) { - case IndeterminateComponent: { - return mountIndeterminateComponent( - current, - workInProgress, - workInProgress.type, - renderLanes - ); - } + if (currentFiber === null) { + return []; + } - case LazyComponent: { - var elementType = workInProgress.elementType; - return mountLazyComponent( - current, - workInProgress, - elementType, - renderLanes - ); - } + var child = currentFiber.child; + var childContextValues = []; - case FunctionComponent: { - var Component = workInProgress.type; - var unresolvedProps = workInProgress.pendingProps; - var resolvedProps = - workInProgress.elementType === Component - ? unresolvedProps - : resolveDefaultProps(Component, unresolvedProps); - return updateFunctionComponent( - current, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - } + if (child !== null) { + collectNearestChildContextValues(child, context, childContextValues); + } - case ClassComponent: { - var _Component = workInProgress.type; - var _unresolvedProps = workInProgress.pendingProps; + return childContextValues; + } - var _resolvedProps = - workInProgress.elementType === _Component - ? _unresolvedProps - : resolveDefaultProps(_Component, _unresolvedProps); + function createScopeInstance() { + return { + DO_NOT_USE_queryAllNodes: DO_NOT_USE_queryAllNodes, + DO_NOT_USE_queryFirstNode: DO_NOT_USE_queryFirstNode, + containsNode: containsNode, + getChildContextValues: getChildContextValues + }; + } - return updateClassComponent( - current, - workInProgress, - _Component, - _resolvedProps, - renderLanes - ); + function markUpdate(workInProgress) { + // Tag the fiber with an update effect. This turns a Placement into + // a PlacementAndUpdate. + workInProgress.flags |= Update; } - case HostRoot: - return updateHostRoot(current, workInProgress, renderLanes); + function markRef(workInProgress) { + workInProgress.flags |= Ref | RefStatic; + } - case HostHoistable: + function appendAllChildren( + parent, + workInProgress, + needsVisibilityToggle, + isHidden + ) { + { + // We only have the top Fiber that was created but we need recurse down its + // children to find all the terminal nodes. + var node = workInProgress.child; + + while (node !== null) { + if (node.tag === HostComponent || node.tag === HostText) { + appendInitialChild(parent, node.stateNode); + } else if (node.tag === HostPortal || false); + else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } - // Fall through + if (node === workInProgress) { + return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow - case HostSingleton: + while (node.sibling === null) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + if (node.return === null || node.return === workInProgress) { + return; + } - // Fall through + node = node.return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow - case HostComponent: - return updateHostComponent$1(current, workInProgress, renderLanes); + node.sibling.return = node.return; + node = node.sibling; + } + } + } // An unfortunate fork of appendAllChildren because we have two different parent types. - case HostText: - return updateHostText$1(); + function updateHostComponent( + current, + workInProgress, + type, + newProps, + renderLanes + ) { + { + // If we have an alternate, that means this is an update and we need to + // schedule a side-effect to do the updates. + var oldProps = current.memoizedProps; - case SuspenseComponent: - return updateSuspenseComponent(current, workInProgress, renderLanes); + if (oldProps === newProps) { + // In mutation mode, this is sufficient for a bailout because + // we won't touch this node even if children changed. + return; + } - case HostPortal: - return updatePortalComponent(current, workInProgress, renderLanes); + markUpdate(workInProgress); + } + } // This function must be called at the very end of the complete phase, because + // it might throw to suspend, and if the resource immediately loads, the work + // loop will resume rendering as if the work-in-progress completed. So it must + // fully complete. + // TODO: This should ideally move to begin phase, but currently the instance is + // not created until the complete phase. For our existing use cases, host nodes + // that suspend don't have children, so it doesn't matter. But that might not + // always be true in the future. - case ForwardRef: { - var type = workInProgress.type; - var _unresolvedProps2 = workInProgress.pendingProps; + function preloadInstanceAndSuspendIfNeeded( + workInProgress, + type, + props, + renderLanes + ) { + { + // If this flag was set previously, we can remove it. The flag + // represents whether this particular set of props might ever need to + // suspend. The safest thing to do is for maySuspendCommit to always + // return true, but if the renderer is reasonably confident that the + // underlying resource won't be evicted, it can return false as a + // performance optimization. + workInProgress.flags &= ~MaySuspendCommit; + return; + } // Mark this fiber with a flag. This gets set on all host instances + } - var _resolvedProps2 = - workInProgress.elementType === type - ? _unresolvedProps2 - : resolveDefaultProps(type, _unresolvedProps2); + function scheduleRetryEffect(workInProgress, retryQueue) { + var wakeables = retryQueue; - return updateForwardRef( - current, - workInProgress, - type, - _resolvedProps2, - renderLanes - ); + if (wakeables !== null) { + // Schedule an effect to attach a retry listener to the promise. + // TODO: Move to passive phase + workInProgress.flags |= Update; + } else { + // This boundary suspended, but no wakeables were added to the retry + // queue. Check if the renderer suspended commit. If so, this means + // that once the fallback is committed, we can immediately retry + // rendering again, because rendering wasn't actually blocked. Only + // the commit phase. + // TODO: Consider a model where we always schedule an immediate retry, even + // for normal Suspense. That way the retry can partially render up to the + // first thing that suspends. + if (workInProgress.flags & ScheduleRetry) { + var retryLane = // TODO: This check should probably be moved into claimNextRetryLane + // I also suspect that we need some further consolidation of offscreen + // and retry lanes. + workInProgress.tag !== OffscreenComponent + ? claimNextRetryLane() + : OffscreenLane; + workInProgress.lanes = mergeLanes(workInProgress.lanes, retryLane); + } + } + } + + function updateHostText(current, workInProgress, oldText, newText) { + { + // If the text differs, mark it as an update. All the work in done in commitWork. + if (oldText !== newText) { + markUpdate(workInProgress); + } + } } - case Fragment: - return updateFragment(current, workInProgress, renderLanes); + function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { + switch (renderState.tailMode) { + case "hidden": { + // Any insertions at the end of the tail list after this point + // should be invisible. If there are already mounted boundaries + // anything before them are not considered for collapsing. + // Therefore we need to go through the whole tail to find if + // there are any. + var tailNode = renderState.tail; + var lastTailNode = null; - case Mode: - return updateMode(current, workInProgress, renderLanes); + while (tailNode !== null) { + if (tailNode.alternate !== null) { + lastTailNode = tailNode; + } - case Profiler: - return updateProfiler(current, workInProgress, renderLanes); + tailNode = tailNode.sibling; + } // Next we're simply going to delete all insertions after the + // last rendered item. - case ContextProvider: - return updateContextProvider(current, workInProgress, renderLanes); + if (lastTailNode === null) { + // All remaining items in the tail are insertions. + renderState.tail = null; + } else { + // Detach the insertion after the last node that was already + // inserted. + lastTailNode.sibling = null; + } - case ContextConsumer: - return updateContextConsumer(current, workInProgress, renderLanes); + break; + } - case MemoComponent: { - var _type2 = workInProgress.type; - var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. + case "collapsed": { + // Any insertions at the end of the tail list after this point + // should be invisible. If there are already mounted boundaries + // anything before them are not considered for collapsing. + // Therefore we need to go through the whole tail to find if + // there are any. + var _tailNode = renderState.tail; + var _lastTailNode = null; - var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); + while (_tailNode !== null) { + if (_tailNode.alternate !== null) { + _lastTailNode = _tailNode; + } - { - if (workInProgress.type !== workInProgress.elementType) { - var outerPropTypes = _type2.propTypes; + _tailNode = _tailNode.sibling; + } // Next we're simply going to delete all insertions after the + // last rendered item. - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - _resolvedProps3, // Resolved for outer only - "prop", - getComponentNameFromType(_type2) - ); + if (_lastTailNode === null) { + // All remaining items in the tail are insertions. + if (!hasRenderedATailFallback && renderState.tail !== null) { + // We suspended during the head. We want to show at least one + // row at the tail. So we'll keep on and cut off the rest. + renderState.tail.sibling = null; + } else { + renderState.tail = null; + } + } else { + // Detach the insertion after the last node that was already + // inserted. + _lastTailNode.sibling = null; } + + break; } } - - _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); - return updateMemoComponent( - current, - workInProgress, - _type2, - _resolvedProps3, - renderLanes - ); } - case SimpleMemoComponent: { - return updateSimpleMemoComponent( - current, - workInProgress, - workInProgress.type, - workInProgress.pendingProps, - renderLanes - ); - } + function bubbleProperties(completedWork) { + var didBailout = + completedWork.alternate !== null && + completedWork.alternate.child === completedWork.child; + var newChildLanes = NoLanes; + var subtreeFlags = NoFlags$1; - case IncompleteClassComponent: { - var _Component2 = workInProgress.type; - var _unresolvedProps4 = workInProgress.pendingProps; + if (!didBailout) { + // Bubble up the earliest expiration time. + if ((completedWork.mode & ProfileMode) !== NoMode) { + // In profiling mode, resetChildExpirationTime is also used to reset + // profiler durations. + var actualDuration = completedWork.actualDuration; + var treeBaseDuration = completedWork.selfBaseDuration; + var child = completedWork.child; - var _resolvedProps4 = - workInProgress.elementType === _Component2 - ? _unresolvedProps4 - : resolveDefaultProps(_Component2, _unresolvedProps4); + while (child !== null) { + newChildLanes = mergeLanes( + newChildLanes, + mergeLanes(child.lanes, child.childLanes) + ); + subtreeFlags |= child.subtreeFlags; + subtreeFlags |= child.flags; // When a fiber is cloned, its actualDuration is reset to 0. This value will + // only be updated if work is done on the fiber (i.e. it doesn't bailout). + // When work is done, it should bubble to the parent's actualDuration. If + // the fiber has not been cloned though, (meaning no work was done), then + // this value will reflect the amount of time spent working on a previous + // render. In that case it should not bubble. We determine whether it was + // cloned by comparing the child pointer. + // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + + actualDuration += child.actualDuration; // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + + treeBaseDuration += child.treeBaseDuration; + child = child.sibling; + } - return mountIncompleteClassComponent( - current, - workInProgress, - _Component2, - _resolvedProps4, - renderLanes - ); - } + completedWork.actualDuration = actualDuration; + completedWork.treeBaseDuration = treeBaseDuration; + } else { + var _child = completedWork.child; - case SuspenseListComponent: { - return updateSuspenseListComponent(current, workInProgress, renderLanes); - } + while (_child !== null) { + newChildLanes = mergeLanes( + newChildLanes, + mergeLanes(_child.lanes, _child.childLanes) + ); + subtreeFlags |= _child.subtreeFlags; + subtreeFlags |= _child.flags; // Update the return pointer so the tree is consistent. This is a code + // smell because it assumes the commit phase is never concurrent with + // the render phase. Will address during refactor to alternate model. - case ScopeComponent: { - { - return updateScopeComponent(current, workInProgress, renderLanes); - } - } + _child.return = completedWork; + _child = _child.sibling; + } + } - case OffscreenComponent: { - return updateOffscreenComponent(current, workInProgress, renderLanes); - } + completedWork.subtreeFlags |= subtreeFlags; + } else { + // Bubble up the earliest expiration time. + if ((completedWork.mode & ProfileMode) !== NoMode) { + // In profiling mode, resetChildExpirationTime is also used to reset + // profiler durations. + var _treeBaseDuration = completedWork.selfBaseDuration; + var _child2 = completedWork.child; + + while (_child2 !== null) { + newChildLanes = mergeLanes( + newChildLanes, + mergeLanes(_child2.lanes, _child2.childLanes) + ); // "Static" flags share the lifetime of the fiber/hook they belong to, + // so we should bubble those up even during a bailout. All the other + // flags have a lifetime only of a single render + commit, so we should + // ignore them. + + subtreeFlags |= _child2.subtreeFlags & StaticMask; + subtreeFlags |= _child2.flags & StaticMask; // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + + _treeBaseDuration += _child2.treeBaseDuration; + _child2 = _child2.sibling; + } - case LegacyHiddenComponent: { - { - return updateLegacyHiddenComponent( - current, - workInProgress, - renderLanes - ); - } - } + completedWork.treeBaseDuration = _treeBaseDuration; + } else { + var _child3 = completedWork.child; + + while (_child3 !== null) { + newChildLanes = mergeLanes( + newChildLanes, + mergeLanes(_child3.lanes, _child3.childLanes) + ); // "Static" flags share the lifetime of the fiber/hook they belong to, + // so we should bubble those up even during a bailout. All the other + // flags have a lifetime only of a single render + commit, so we should + // ignore them. + + subtreeFlags |= _child3.subtreeFlags & StaticMask; + subtreeFlags |= _child3.flags & StaticMask; // Update the return pointer so the tree is consistent. This is a code + // smell because it assumes the commit phase is never concurrent with + // the render phase. Will address during refactor to alternate model. + + _child3.return = completedWork; + _child3 = _child3.sibling; + } + } - case CacheComponent: { - { - return updateCacheComponent(current, workInProgress, renderLanes); + completedWork.subtreeFlags |= subtreeFlags; } + + completedWork.childLanes = newChildLanes; + return didBailout; } - case TracingMarkerComponent: { - if (enableTransitionTracing) { - return updateTracingMarkerComponent( - current, - workInProgress, - renderLanes - ); - } + function completeDehydratedSuspenseBoundary( + current, + workInProgress, + nextState + ) { + var wasHydrated = popHydrationState(); - break; - } - } + if (nextState !== null && nextState.dehydrated !== null) { + // We might be inside a hydration state the first time we're picking up this + // Suspense boundary, and also after we've reentered it for further hydration. + if (current === null) { + if (!wasHydrated) { + throw new Error( + "A dehydrated suspense component was completed without a hydrated node. " + + "This is probably a bug in React." + ); + } - throw new Error( - "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in " + - "React. Please file an issue." - ); -} + prepareToHydrateHostSuspenseInstance(); + bubbleProperties(workInProgress); -var valueCursor = createCursor(null); + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + var isTimedOutSuspense = nextState !== null; -var renderer2CursorDEV; + if (isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var primaryChildFragment = workInProgress.child; -{ - renderer2CursorDEV = createCursor(null); -} + if (primaryChildFragment !== null) { + // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + primaryChildFragment.treeBaseDuration; + } + } + } + } -var rendererSigil; + return false; + } else { + if ((workInProgress.flags & DidCapture) === NoFlags$1) { + // This boundary did not suspend so it's now hydrated and unsuspended. + workInProgress.memoizedState = null; + } // If nothing suspended, we need to schedule an effect to mark this boundary + // as having hydrated so events know that they're free to be invoked. + // It's also a signal to replay events and the suspense callback. + // If something suspended, schedule an effect to attach retry listeners. + // So we might as well always mark this. -{ - // Use this to detect multiple renderers using the same context - rendererSigil = {}; -} + workInProgress.flags |= Update; + bubbleProperties(workInProgress); -var currentlyRenderingFiber = null; -var lastContextDependency = null; -var lastFullyObservedContext = null; -var isDisallowedContextReadInDEV = false; -function resetContextDependencies() { - // This is called right before React yields execution, to ensure `readContext` - // cannot be called outside the render phase. - currentlyRenderingFiber = null; - lastContextDependency = null; - lastFullyObservedContext = null; - - { - isDisallowedContextReadInDEV = false; - } -} -function enterDisallowedContextReadInDEV() { - { - isDisallowedContextReadInDEV = true; - } -} -function exitDisallowedContextReadInDEV() { - { - isDisallowedContextReadInDEV = false; - } -} -function pushProvider(providerFiber, context, nextValue) { - { - push(valueCursor, context._currentValue2, providerFiber); - context._currentValue2 = nextValue; + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + var _isTimedOutSuspense = nextState !== null; - { - push(renderer2CursorDEV, context._currentRenderer2, providerFiber); + if (_isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var _primaryChildFragment = workInProgress.child; - if ( - context._currentRenderer2 !== undefined && - context._currentRenderer2 !== null && - context._currentRenderer2 !== rendererSigil - ) { - error( - "Detected multiple renderers concurrently rendering the " + - "same context provider. This is currently unsupported." - ); - } + if (_primaryChildFragment !== null) { + // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + _primaryChildFragment.treeBaseDuration; + } + } + } + } - context._currentRenderer2 = rendererSigil; - } - } -} -function popProvider(context, providerFiber) { - var currentValue = valueCursor.current; + return false; + } + } else { + // Successfully completed this tree. If this was a forced client render, + // there may have been recoverable errors during first hydration + // attempt. If so, add them to a queue so we can log them in the + // commit phase. + upgradeHydrationErrorsToRecoverable(); // Fall through to normal Suspense path - { - { - context._currentValue2 = currentValue; + return true; + } } - { - var currentRenderer2 = renderer2CursorDEV.current; - pop(renderer2CursorDEV, providerFiber); - context._currentRenderer2 = currentRenderer2; - } - } + function completeWork(current, workInProgress, renderLanes) { + var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing - pop(valueCursor, providerFiber); -} -function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { - // Update the child lanes of all the ancestors, including the alternates. - var node = parent; + switch (workInProgress.tag) { + case IndeterminateComponent: + case LazyComponent: + case SimpleMemoComponent: + case FunctionComponent: + case ForwardRef: + case Fragment: + case Mode: + case Profiler: + case ContextConsumer: + case MemoComponent: + bubbleProperties(workInProgress); + return null; - while (node !== null) { - var alternate = node.alternate; + case ClassComponent: { + var Component = workInProgress.type; - if (!isSubsetOfLanes(node.childLanes, renderLanes)) { - node.childLanes = mergeLanes(node.childLanes, renderLanes); + if (isContextProvider(Component)) { + popContext(workInProgress); + } - if (alternate !== null) { - alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); - } - } else if ( - alternate !== null && - !isSubsetOfLanes(alternate.childLanes, renderLanes) - ) { - alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); - } else; + bubbleProperties(workInProgress); + return null; + } - if (node === propagationRoot) { - break; - } + case HostRoot: { + var fiberRoot = workInProgress.stateNode; - node = node.return; - } + if (enableTransitionTracing) { + var transitions = getWorkInProgressTransitions(); // We set the Passive flag here because if there are new transitions, + // we will need to schedule callbacks and process the transitions, + // which we do in the passive phase - { - if (node !== propagationRoot) { - 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." - ); - } - } -} -function propagateContextChange(workInProgress, context, renderLanes) { - if (enableLazyContextPropagation) { - // TODO: This path is only used by Cache components. Update - // lazilyPropagateParentContextChanges to look for Cache components so they - // can take advantage of lazy propagation. - var forcePropagateEntireTree = true; - propagateContextChanges( - workInProgress, - [context], - renderLanes, - forcePropagateEntireTree - ); - } else { - propagateContextChange_eager(workInProgress, context, renderLanes); - } -} + if (transitions !== null) { + workInProgress.flags |= Passive$1; + } + } -function propagateContextChange_eager(workInProgress, context, renderLanes) { - // Only used by eager implementation - if (enableLazyContextPropagation) { - return; - } + { + var previousCache = null; - var fiber = workInProgress.child; + if (current !== null) { + previousCache = current.memoizedState.cache; + } - if (fiber !== null) { - // Set the return pointer of the child to the work-in-progress fiber. - fiber.return = workInProgress; - } + var cache = workInProgress.memoizedState.cache; - while (fiber !== null) { - var nextFiber = void 0; // Visit this fiber. + if (cache !== previousCache) { + // Run passive effects to retain/release the cache. + workInProgress.flags |= Passive$1; + } - var list = fiber.dependencies; + popCacheProvider(workInProgress); + } - if (list !== null) { - nextFiber = fiber.child; - var dependency = list.firstContext; + if (enableTransitionTracing) { + popRootMarkerInstance(workInProgress); + } - while (dependency !== null) { - // Check if the context matches. - if (dependency.context === context) { - // Match! Schedule an update on this fiber. - if (fiber.tag === ClassComponent) { - // Schedule a force update on the work-in-progress. - var lane = pickArbitraryLane(renderLanes); - var update = createUpdate(lane); - update.tag = ForceUpdate; // TODO: Because we don't have a work-in-progress, this will add the - // update to the current fiber, too, which means it will persist even if - // this render is thrown away. Since it's a race condition, not sure it's - // worth fixing. - // Inlined `enqueueUpdate` to remove interleaved update check + popRootTransition(workInProgress); + popHostContainer(workInProgress); + popTopLevelContextObject(workInProgress); - var updateQueue = fiber.updateQueue; + if (fiberRoot.pendingContext) { + fiberRoot.context = fiberRoot.pendingContext; + fiberRoot.pendingContext = null; + } - if (updateQueue === null); - else { - var sharedQueue = updateQueue.shared; - var pending = sharedQueue.pending; + if (current === null || current.child === null) { + // If we hydrated, pop so that we can delete any remaining children + // that weren't hydrated. + var wasHydrated = popHydrationState(); - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; + if (wasHydrated) { + // If we hydrated, then we'll need to schedule an update for + // the commit side-effects on the root. + markUpdate(workInProgress); + } else { + if (current !== null) { + var prevState = current.memoizedState; + + if ( + // Check if this is a client root + !prevState.isDehydrated || // Check if we reverted to client rendering (e.g. due to an error) + (workInProgress.flags & ForceClientRender) !== NoFlags$1 + ) { + // Schedule an effect to clear this container at the start of the + // next commit. This handles the case of React rendering into a + // container with previous children. It's also safe to do for + // updates too, because current.child would only be null if the + // previous render was null (so the container would already + // be empty). + workInProgress.flags |= Snapshot; // If this was a forced client render, there may have been + // recoverable errors during first hydration attempt. If so, add + // them to a queue so we can log them in the commit phase. + + upgradeHydrationErrorsToRecoverable(); + } } + } + } + bubbleProperties(workInProgress); - sharedQueue.pending = update; + if (enableTransitionTracing) { + if ((workInProgress.subtreeFlags & Visibility) !== NoFlags$1) { + // If any of our suspense children toggle visibility, this means that + // the pending boundaries array needs to be updated, which we only + // do in the passive phase. + workInProgress.flags |= Passive$1; } } - fiber.lanes = mergeLanes(fiber.lanes, renderLanes); - var alternate = fiber.alternate; + return null; + } + + case HostHoistable: - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, renderLanes); - } + case HostSingleton: - scheduleContextWorkOnParentPath( - fiber.return, - renderLanes, - workInProgress - ); // Mark the updated lanes on the list, too. + case HostComponent: { + popHostContext(workInProgress); + var _type2 = workInProgress.type; + + if (current !== null && workInProgress.stateNode != null) { + updateHostComponent(current, workInProgress, _type2, newProps); + + if (current.ref !== workInProgress.ref) { + markRef(workInProgress); + } + } else { + if (!newProps) { + if (workInProgress.stateNode === null) { + 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." + ); + } // This can happen when we abort work. - list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the - // dependency list. + bubbleProperties(workInProgress); + return null; + } - break; - } + getHostContext(); // TODO: Move createInstance to beginWork and keep it on a context + // "stack" as the parent. Then append children as we go in beginWork + // or completeWork depending on whether we want to add them top->down or + // bottom->up. Top->down is faster in IE11. - dependency = dependency.next; - } - } else if (fiber.tag === ContextProvider) { - // Don't scan deeper if this is a matching provider - nextFiber = fiber.type === workInProgress.type ? null : fiber.child; - } else if (fiber.tag === DehydratedFragment) { - // If a dehydrated suspense boundary is in this subtree, we don't know - // if it will have any context consumers in it. The best we can do is - // mark it as having updates. - var parentSuspense = fiber.return; + var _wasHydrated2 = popHydrationState(); - if (parentSuspense === null) { - throw new Error( - "We just came from a parent so we must have had a parent. This is a bug in React." - ); - } + if (_wasHydrated2) { + // TODO: Move this and createInstance step into the beginPhase + // to consolidate. + prepareToHydrateHostInstance(); + } else { + getRootHostContainer(); - parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); - var _alternate = parentSuspense.alternate; + var _instance3 = createInstance(_type2, newProps); // TODO: For persistent renderers, we should pass children as part + // of the initial instance creation - if (_alternate !== null) { - _alternate.lanes = mergeLanes(_alternate.lanes, renderLanes); - } // This is intentionally passing this fiber as the parent - // because we want to schedule this fiber as having work - // on its children. We'll use the childLanes on - // this fiber to indicate that a context has changed. + appendAllChildren(_instance3, workInProgress); + workInProgress.stateNode = _instance3; // Certain renderers require commit-time effects for initial mount. + } - scheduleContextWorkOnParentPath( - parentSuspense, - renderLanes, - workInProgress - ); - nextFiber = fiber.sibling; - } else { - // Traverse down. - nextFiber = fiber.child; - } + if (workInProgress.ref !== null) { + // If there is a ref on a host node we need to schedule a callback + markRef(workInProgress); + } + } - if (nextFiber !== null) { - // Set the return pointer of the child to the work-in-progress fiber. - nextFiber.return = fiber; - } else { - // No child. Traverse to next sibling. - nextFiber = fiber; + bubbleProperties(workInProgress); // This must come at the very end of the complete phase, because it might + // throw to suspend, and if the resource immediately loads, the work loop + // will resume rendering as if the work-in-progress completed. So it must + // fully complete. - while (nextFiber !== null) { - if (nextFiber === workInProgress) { - // We're back to the root of this subtree. Exit. - nextFiber = null; - break; + preloadInstanceAndSuspendIfNeeded(workInProgress); + return null; } - var sibling = nextFiber.sibling; + case HostText: { + var newText = newProps; - if (sibling !== null) { - // Set the return pointer of the sibling to the work-in-progress fiber. - sibling.return = nextFiber.return; - nextFiber = sibling; - break; - } // No more siblings. Traverse up. + if (current && workInProgress.stateNode != null) { + var oldText = current.memoizedProps; // If we have an alternate, that means this is an update and we need + // to schedule a side-effect to do the updates. - nextFiber = nextFiber.return; - } - } + updateHostText(current, workInProgress, oldText, newText); + } else { + if (typeof newText !== "string") { + if (workInProgress.stateNode === null) { + 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." + ); + } // This can happen when we abort work. + } - fiber = nextFiber; - } -} + getRootHostContainer(); -function propagateContextChanges( - workInProgress, - contexts, - renderLanes, - forcePropagateEntireTree -) { - // Only used by lazy implementation - if (!enableLazyContextPropagation) { - return; - } - - var fiber = workInProgress.child; - - if (fiber !== null) { - // Set the return pointer of the child to the work-in-progress fiber. - fiber.return = workInProgress; - } - - while (fiber !== null) { - var nextFiber = void 0; // Visit this fiber. - - var list = fiber.dependencies; - - if (list !== null) { - nextFiber = fiber.child; - var dep = list.firstContext; - - findChangedDep: while (dep !== null) { - // Assigning these to constants to help Flow - var dependency = dep; - var consumer = fiber; - - for (var i = 0; i < contexts.length; i++) { - var context = contexts[i]; // Check if the context matches. - // TODO: Compare selected values to bail out early. - - if (dependency.context === context) { - // Match! Schedule an update on this fiber. - // In the lazy implementation, don't mark a dirty flag on the - // dependency itself. Not all changes are propagated, so we can't - // rely on the propagation function alone to determine whether - // something has changed; the consumer will check. In the future, we - // could add back a dirty flag as an optimization to avoid double - // checking, but until we have selectors it's not really worth - // the trouble. - consumer.lanes = mergeLanes(consumer.lanes, renderLanes); - var alternate = consumer.alternate; - - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, renderLanes); - } - - scheduleContextWorkOnParentPath( - consumer.return, - renderLanes, - workInProgress - ); + getHostContext(); - if (!forcePropagateEntireTree) { - // During lazy propagation, when we find a match, we can defer - // propagating changes to the children, because we're going to - // visit them during render. We should continue propagating the - // siblings, though - nextFiber = null; - } // Since we already found a match, we can stop traversing the - // dependency list. + var _wasHydrated3 = popHydrationState(); - break findChangedDep; + if (_wasHydrated3) { + if (prepareToHydrateHostTextInstance()) { + markUpdate(workInProgress); + } + } else { + workInProgress.stateNode = createTextInstance(newText); + } } + + bubbleProperties(workInProgress); + return null; } - dep = dependency.next; - } - } else if (fiber.tag === DehydratedFragment) { - // If a dehydrated suspense boundary is in this subtree, we don't know - // if it will have any context consumers in it. The best we can do is - // mark it as having updates. - var parentSuspense = fiber.return; + case SuspenseComponent: { + popSuspenseHandler(workInProgress); + var nextState = workInProgress.memoizedState; // Special path for dehydrated boundaries. We may eventually move this + // to its own fiber type so that we can add other kinds of hydration + // boundaries that aren't associated with a Suspense tree. In anticipation + // of such a refactor, all the hydration logic is contained in + // this branch. - if (parentSuspense === null) { - throw new Error( - "We just came from a parent so we must have had a parent. This is a bug in React." - ); - } + if ( + current === null || + (current.memoizedState !== null && + current.memoizedState.dehydrated !== null) + ) { + var fallthroughToNormalSuspensePath = + completeDehydratedSuspenseBoundary( + current, + workInProgress, + nextState + ); - parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); - var _alternate2 = parentSuspense.alternate; + if (!fallthroughToNormalSuspensePath) { + if (workInProgress.flags & ForceClientRender) { + // Special case. There were remaining unhydrated nodes. We treat + // this as a mismatch. Revert to client rendering. + return workInProgress; + } else { + // Did not finish hydrating, either because this is the initial + // render or because something suspended. + return null; + } + } // Continue with the normal Suspense path. + } - if (_alternate2 !== null) { - _alternate2.lanes = mergeLanes(_alternate2.lanes, renderLanes); - } // This is intentionally passing this fiber as the parent - // because we want to schedule this fiber as having work - // on its children. We'll use the childLanes on - // this fiber to indicate that a context has changed. + if ((workInProgress.flags & DidCapture) !== NoFlags$1) { + // Something suspended. Re-render with the fallback children. + workInProgress.lanes = renderLanes; // Do not reset the effect list. - scheduleContextWorkOnParentPath( - parentSuspense, - renderLanes, - workInProgress - ); - nextFiber = null; - } else { - // Traverse down. - nextFiber = fiber.child; - } + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } // Don't bubble properties in this case. - if (nextFiber !== null) { - // Set the return pointer of the child to the work-in-progress fiber. - nextFiber.return = fiber; - } else { - // No child. Traverse to next sibling. - nextFiber = fiber; + return workInProgress; + } - while (nextFiber !== null) { - if (nextFiber === workInProgress) { - // We're back to the root of this subtree. Exit. - nextFiber = null; - break; - } + var nextDidTimeout = nextState !== null; + var prevDidTimeout = + current !== null && current.memoizedState !== null; - var sibling = nextFiber.sibling; + if (nextDidTimeout) { + var offscreenFiber = workInProgress.child; + var _previousCache = null; - if (sibling !== null) { - // Set the return pointer of the sibling to the work-in-progress fiber. - sibling.return = nextFiber.return; - nextFiber = sibling; - break; - } // No more siblings. Traverse up. + if ( + offscreenFiber.alternate !== null && + offscreenFiber.alternate.memoizedState !== null && + offscreenFiber.alternate.memoizedState.cachePool !== null + ) { + _previousCache = + offscreenFiber.alternate.memoizedState.cachePool.pool; + } - nextFiber = nextFiber.return; - } - } + var _cache = null; - fiber = nextFiber; - } -} + if ( + offscreenFiber.memoizedState !== null && + offscreenFiber.memoizedState.cachePool !== null + ) { + _cache = offscreenFiber.memoizedState.cachePool.pool; + } -function lazilyPropagateParentContextChanges( - current, - workInProgress, - renderLanes -) { - var forcePropagateEntireTree = false; - propagateParentContextChanges( - current, - workInProgress, - renderLanes, - forcePropagateEntireTree - ); -} // Used for propagating a deferred tree (Suspense, Offscreen). We must propagate -// to the entire subtree, because we won't revisit it until after the current -// render has completed, at which point we'll have lost track of which providers -// have changed. - -function propagateParentContextChangesToDeferredTree( - current, - workInProgress, - renderLanes -) { - var forcePropagateEntireTree = true; - propagateParentContextChanges( - current, - workInProgress, - renderLanes, - forcePropagateEntireTree - ); -} + if (_cache !== _previousCache) { + // Run passive effects to retain/release the cache. + offscreenFiber.flags |= Passive$1; + } + } // If the suspended state of the boundary changes, we need to schedule + // a passive effect, which is when we process the transitions + + if (nextDidTimeout !== prevDidTimeout) { + if (enableTransitionTracing) { + var _offscreenFiber = workInProgress.child; + _offscreenFiber.flags |= Passive$1; + } // If the suspended state of the boundary changes, we need to schedule + // an effect to toggle the subtree's visibility. When we switch from + // fallback -> primary, the inner Offscreen fiber schedules this effect + // as part of its normal complete phase. But when we switch from + // primary -> fallback, the inner Offscreen fiber does not have a complete + // phase. So we need to schedule its effect here. + // + // We also use this flag to connect/disconnect the effects, but the same + // logic applies: when re-connecting, the Offscreen fiber's complete + // phase will handle scheduling the effect. It's only when the fallback + // is active that we have to do anything special. + + if (nextDidTimeout) { + var _offscreenFiber2 = workInProgress.child; + _offscreenFiber2.flags |= Visibility; + } + } -function propagateParentContextChanges( - current, - workInProgress, - renderLanes, - forcePropagateEntireTree -) { - if (!enableLazyContextPropagation) { - return; - } // Collect all the parent providers that changed. Since this is usually small - // number, we use an Array instead of Set. + var retryQueue = workInProgress.updateQueue; + scheduleRetryEffect(workInProgress, retryQueue); - var contexts = null; - var parent = workInProgress; - var isInsidePropagationBailout = false; + if ( + workInProgress.updateQueue !== null && + workInProgress.memoizedProps.suspenseCallback != null + ) { + // Always notify the callback + // TODO: Move to passive phase + workInProgress.flags |= Update; + } - while (parent !== null) { - if (!isInsidePropagationBailout) { - if ((parent.flags & NeedsPropagation) !== NoFlags$1) { - isInsidePropagationBailout = true; - } else if ((parent.flags & DidPropagateContext) !== NoFlags$1) { - break; - } - } + bubbleProperties(workInProgress); - if (parent.tag === ContextProvider) { - var currentParent = parent.alternate; + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + if (nextDidTimeout) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var primaryChildFragment = workInProgress.child; + + if (primaryChildFragment !== null) { + // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + primaryChildFragment.treeBaseDuration; + } + } + } + } - if (currentParent === null) { - throw new Error("Should have a current fiber. This is a bug in React."); - } + return null; + } - var oldProps = currentParent.memoizedProps; + case HostPortal: + popHostContainer(workInProgress); - if (oldProps !== null) { - var providerType = parent.type; - var context = providerType._context; - var newProps = parent.pendingProps; - var newValue = newProps.value; - var oldValue = oldProps.value; + bubbleProperties(workInProgress); + return null; - if (!objectIs(newValue, oldValue)) { - if (contexts !== null) { - contexts.push(context); - } else { - contexts = [context]; + case ContextProvider: + // Pop provider fiber + var context = workInProgress.type._context; + popProvider(context, workInProgress); + bubbleProperties(workInProgress); + return null; + + case IncompleteClassComponent: { + // Same as class component case. I put it down here so that the tags are + // sequential to ensure this switch is compiled to a jump table. + var _Component = workInProgress.type; + + if (isContextProvider(_Component)) { + popContext(workInProgress); } - } - } - } - parent = parent.return; - } + bubbleProperties(workInProgress); + return null; + } - if (contexts !== null) { - // If there were any changed providers, search through the children and - // propagate their changes. - propagateContextChanges( - workInProgress, - contexts, - renderLanes, - forcePropagateEntireTree - ); - } // This is an optimization so that we only propagate once per subtree. If a - // deeply nested child bails out, and it calls this propagation function, it - // uses this flag to know that the remaining ancestor providers have already - // been propagated. - // - // NOTE: This optimization is only necessary because we sometimes enter the - // begin phase of nodes that don't have any work scheduled on them — - // specifically, the siblings of a node that _does_ have scheduled work. The - // siblings will bail out and call this function again, even though we already - // propagated content changes to it and its subtree. So we use this flag to - // mark that the parent providers already propagated. - // - // Unfortunately, though, we need to ignore this flag when we're inside a - // tree whose context propagation was deferred — that's what the - // `NeedsPropagation` flag is for. - // - // If we could instead bail out before entering the siblings' begin phase, - // then we could remove both `DidPropagateContext` and `NeedsPropagation`. - // Consider this as part of the next refactor to the fiber tree structure. - - workInProgress.flags |= DidPropagateContext; -} + case SuspenseListComponent: { + popSuspenseListContext(workInProgress); + var renderState = workInProgress.memoizedState; -function checkIfContextChanged(currentDependencies) { - if (!enableLazyContextPropagation) { - return false; - } // Iterate over the current dependencies to see if something changed. This - // only gets called if props and state has already bailed out, so it's a - // relatively uncommon path, except at the root of a changed subtree. - // Alternatively, we could move these comparisons into `readContext`, but - // that's a much hotter path, so I think this is an appropriate trade off. + if (renderState === null) { + // We're running in the default, "independent" mode. + // We don't do anything in this mode. + bubbleProperties(workInProgress); + return null; + } - var dependency = currentDependencies.firstContext; + var didSuspendAlready = + (workInProgress.flags & DidCapture) !== NoFlags$1; + var renderedTail = renderState.rendering; + + if (renderedTail === null) { + // We just rendered the head. + if (!didSuspendAlready) { + // This is the first pass. We need to figure out if anything is still + // suspended in the rendered set. + // If new content unsuspended, but there's still some content that + // didn't. Then we need to do a second pass that forces everything + // to keep showing their fallbacks. + // We might be suspended if something in this render pass suspended, or + // something in the previous committed pass suspended. Otherwise, + // there's no chance so we can skip the expensive call to + // findFirstSuspended. + var cannotBeSuspended = + renderHasNotSuspendedYet() && + (current === null || + (current.flags & DidCapture) === NoFlags$1); + + if (!cannotBeSuspended) { + var row = workInProgress.child; + + while (row !== null) { + var suspended = findFirstSuspended(row); + + if (suspended !== null) { + didSuspendAlready = true; + workInProgress.flags |= DidCapture; + cutOffTailIfNeeded(renderState, false); // If this is a newly suspended tree, it might not get committed as + // part of the second pass. In that case nothing will subscribe to + // its thenables. Instead, we'll transfer its thenables to the + // SuspenseList so that it can retry if they resolve. + // There might be multiple of these in the list but since we're + // going to wait for all of them anyway, it doesn't really matter + // which ones gets to ping. In theory we could get clever and keep + // track of how many dependencies remain but it gets tricky because + // in the meantime, we can add/remove/change items and dependencies. + // We might bail out of the loop before finding any but that + // doesn't matter since that means that the other boundaries that + // we did find already has their listeners attached. + + var _retryQueue = suspended.updateQueue; + workInProgress.updateQueue = _retryQueue; + scheduleRetryEffect(workInProgress, _retryQueue); // Rerender the whole list, but this time, we'll force fallbacks + // to stay in place. + // Reset the effect flags before doing the second pass since that's now invalid. + // Reset the child fibers to their original state. + + workInProgress.subtreeFlags = NoFlags$1; + resetChildFibers(workInProgress, renderLanes); // Set up the Suspense List Context to force suspense and + // immediately rerender the children. + + pushSuspenseListContext( + workInProgress, + setShallowSuspenseListContext( + suspenseStackCursor.current, + ForceSuspenseFallback + ) + ); // Don't bubble properties in this case. + + return workInProgress.child; + } - while (dependency !== null) { - var context = dependency.context; - var newValue = context._currentValue2; - var oldValue = dependency.memoizedValue; + row = row.sibling; + } + } - if (!objectIs(newValue, oldValue)) { - return true; - } + if ( + renderState.tail !== null && + now$1() > getRenderTargetTime() + ) { + // We have already passed our CPU deadline but we still have rows + // left in the tail. We'll just give up further attempts to render + // the main content and only render fallbacks. + workInProgress.flags |= DidCapture; + didSuspendAlready = true; + cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. + + workInProgress.lanes = SomeRetryLane; + } + } else { + cutOffTailIfNeeded(renderState, false); + } // Next we're going to render the tail. + } else { + // Append the rendered row to the child list. + if (!didSuspendAlready) { + var _suspended = findFirstSuspended(renderedTail); - dependency = dependency.next; - } + if (_suspended !== null) { + workInProgress.flags |= DidCapture; + didSuspendAlready = true; // Ensure we transfer the update queue to the parent so that it doesn't + // get lost if this row ends up dropped during a second pass. + + var _retryQueue2 = _suspended.updateQueue; + workInProgress.updateQueue = _retryQueue2; + scheduleRetryEffect(workInProgress, _retryQueue2); + cutOffTailIfNeeded(renderState, true); // This might have been modified. + + if ( + renderState.tail === null && + renderState.tailMode === "hidden" && + !renderedTail.alternate && + !getIsHydrating() // We don't cut it if we're hydrating. + ) { + // We're done. + bubbleProperties(workInProgress); + return null; + } + } else if ( + // The time it took to render last row is greater than the remaining + // time we have to render. So rendering one more row would likely + // exceed it. + now$1() * 2 - renderState.renderingStartTime > + getRenderTargetTime() && + renderLanes !== OffscreenLane + ) { + // We have now passed our CPU deadline and we'll just give up further + // attempts to render the main content and only render fallbacks. + // The assumption is that this is usually faster. + workInProgress.flags |= DidCapture; + didSuspendAlready = true; + cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. + + workInProgress.lanes = SomeRetryLane; + } + } - return false; -} -function prepareToReadContext(workInProgress, renderLanes) { - currentlyRenderingFiber = workInProgress; - lastContextDependency = null; - lastFullyObservedContext = null; - var dependencies = workInProgress.dependencies; - - if (dependencies !== null) { - if (enableLazyContextPropagation) { - // Reset the work-in-progress list - dependencies.firstContext = null; - } else { - var firstContext = dependencies.firstContext; + if (renderState.isBackwards) { + // The effect list of the backwards tail will have been added + // to the end. This breaks the guarantee that life-cycles fire in + // sibling order but that isn't a strong guarantee promised by React. + // Especially since these might also just pop in during future commits. + // Append to the beginning of the list. + renderedTail.sibling = workInProgress.child; + workInProgress.child = renderedTail; + } else { + var previousSibling = renderState.last; - if (firstContext !== null) { - if (includesSomeLane(dependencies.lanes, renderLanes)) { - // Context list has a pending update. Mark that this fiber performed work. - markWorkInProgressReceivedUpdate(); - } // Reset the work-in-progress list + if (previousSibling !== null) { + previousSibling.sibling = renderedTail; + } else { + workInProgress.child = renderedTail; + } - dependencies.firstContext = null; - } - } - } -} -function readContext(context) { - { - // This warning would fire if you read context inside a Hook like useMemo. - // Unlike the class check below, it's not enforced in production for perf. - if (isDisallowedContextReadInDEV) { - 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()." - ); - } - } + renderState.last = renderedTail; + } + } - return readContextForConsumer(currentlyRenderingFiber, context); -} -function readContextDuringReconcilation(consumer, context, renderLanes) { - if (currentlyRenderingFiber === null) { - prepareToReadContext(consumer, renderLanes); - } + if (renderState.tail !== null) { + // We still have tail rows to render. + // Pop a row. + var next = renderState.tail; + renderState.rendering = next; + renderState.tail = next.sibling; + renderState.renderingStartTime = now$1(); + next.sibling = null; // Restore the context. + // TODO: We can probably just avoid popping it instead and only + // setting it the first time we go from not suspended to suspended. + + var suspenseContext = suspenseStackCursor.current; + + if (didSuspendAlready) { + suspenseContext = setShallowSuspenseListContext( + suspenseContext, + ForceSuspenseFallback + ); + } else { + suspenseContext = + setDefaultShallowSuspenseListContext(suspenseContext); + } - return readContextForConsumer(consumer, context); -} + pushSuspenseListContext(workInProgress, suspenseContext); // Do a pass over the next row. + // Don't bubble properties in this case. -function readContextForConsumer(consumer, context) { - var value = context._currentValue2; + return next; + } - if (lastFullyObservedContext === context); - else { - var contextItem = { - context: context, - memoizedValue: value, - next: null - }; + bubbleProperties(workInProgress); + return null; + } - if (lastContextDependency === null) { - if (consumer === null) { - 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()." - ); - } // This is the first dependency for this component. Create a new list. + case ScopeComponent: { + { + if (current === null) { + var scopeInstance = createScopeInstance(); + workInProgress.stateNode = scopeInstance; + prepareScopeUpdate(); + + if (workInProgress.ref !== null) { + markRef(workInProgress); + markUpdate(workInProgress); + } + } else { + if (workInProgress.ref !== null) { + markUpdate(workInProgress); + } - lastContextDependency = contextItem; - consumer.dependencies = { - lanes: NoLanes, - firstContext: contextItem - }; + if (current.ref !== workInProgress.ref) { + markRef(workInProgress); + } + } - if (enableLazyContextPropagation) { - consumer.flags |= NeedsPropagation; - } - } else { - // Append a new context item. - lastContextDependency = lastContextDependency.next = contextItem; - } - } + bubbleProperties(workInProgress); + return null; + } + } - return value; -} + case OffscreenComponent: + case LegacyHiddenComponent: { + popSuspenseHandler(workInProgress); + popHiddenContext(workInProgress); + var _nextState = workInProgress.memoizedState; + var nextIsHidden = _nextState !== null; // Schedule a Visibility effect if the visibility has changed -// replace it with a lightweight shim that only has the features we use. + if (workInProgress.tag === LegacyHiddenComponent); + else { + if (current !== null) { + var _prevState = current.memoizedState; + var prevIsHidden = _prevState !== null; -var AbortControllerLocal = - typeof AbortController !== "undefined" - ? AbortController // $FlowFixMe[missing-this-annot] - : // $FlowFixMe[prop-missing] - function AbortControllerShim() { - var listeners = []; - var signal = (this.signal = { - aborted: false, - addEventListener: function (type, listener) { - listeners.push(listener); + if (prevIsHidden !== nextIsHidden) { + workInProgress.flags |= Visibility; + } + } else { + // On initial mount, we only need a Visibility effect if the tree + // is hidden. + if (nextIsHidden) { + workInProgress.flags |= Visibility; + } + } } - }); - this.abort = function () { - signal.aborted = true; - listeners.forEach(function (listener) { - return listener(); - }); - }; - }; // Intentionally not named imports because Rollup would -// use dynamic dispatch for CommonJS interop named imports. - -var scheduleCallback$1 = Scheduler.unstable_scheduleCallback, - NormalPriority = Scheduler.unstable_NormalPriority; -var CacheContext = { - $$typeof: REACT_CONTEXT_TYPE, - // We don't use Consumer/Provider for Cache components. So we'll cheat. - Consumer: null, - Provider: null, - // We'll initialize these at the root. - _currentValue: null, - _currentValue2: null, - _threadCount: 0, - _defaultValue: null, - _globalName: null -}; - -{ - CacheContext._currentRenderer = null; - CacheContext._currentRenderer2 = null; -} // Creates a new empty Cache instance with a ref-count of 0. The caller is responsible -// for retaining the cache once it is in use (retainCache), and releasing the cache -// once it is no longer needed (releaseCache). - -function createCache() { - var cache = { - controller: new AbortControllerLocal(), - data: new Map(), - refCount: 0 - }; - return cache; -} -function retainCache(cache) { - { - if (cache.controller.signal.aborted) { - warn( - "A cache instance was retained after it was already freed. " + - "This likely indicates a bug in React." - ); - } - } + if ( + !nextIsHidden || + (workInProgress.mode & ConcurrentMode) === NoMode + ) { + bubbleProperties(workInProgress); + } else { + // Don't bubble properties for hidden children unless we're rendering + // at offscreen priority. + if ( + includesSomeLane(renderLanes, OffscreenLane) && // Also don't bubble if the tree suspended + (workInProgress.flags & DidCapture) === NoLanes + ) { + bubbleProperties(workInProgress); // Check if there was an insertion or update in the hidden subtree. + // If so, we need to hide those nodes in the commit phase, so + // schedule a visibility effect. - cache.refCount++; -} // Cleanup a cache instance, potentially freeing it if there are no more references + if ( + workInProgress.tag !== LegacyHiddenComponent && + workInProgress.subtreeFlags & (Placement | Update) + ) { + workInProgress.flags |= Visibility; + } + } + } -function releaseCache(cache) { - cache.refCount--; + var offscreenQueue = workInProgress.updateQueue; - { - if (cache.refCount < 0) { - warn( - "A cache instance was released after it was already freed. " + - "This likely indicates a bug in React." - ); - } - } + if (offscreenQueue !== null) { + var _retryQueue3 = offscreenQueue.retryQueue; + scheduleRetryEffect(workInProgress, _retryQueue3); + } - if (cache.refCount === 0) { - scheduleCallback$1(NormalPriority, function () { - cache.controller.abort(); - }); - } -} -function pushCacheProvider(workInProgress, cache) { - pushProvider(workInProgress, CacheContext, cache); -} -function popCacheProvider(workInProgress, cache) { - popProvider(CacheContext, workInProgress); -} + { + var _previousCache2 = null; -var ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig; -var NoTransition = null; -function requestCurrentTransition() { - return ReactCurrentBatchConfig$1.transition; -} // When retrying a Suspense/Offscreen boundary, we restore the cache that was -// used during the previous render by placing it here, on the stack. + if ( + current !== null && + current.memoizedState !== null && + current.memoizedState.cachePool !== null + ) { + _previousCache2 = current.memoizedState.cachePool.pool; + } -var resumedCache = createCursor(null); // During the render/synchronous commit phase, we don't actually process the -// transitions. Therefore, we want to lazily combine transitions. Instead of -// comparing the arrays of transitions when we combine them and storing them -// and filtering out the duplicates, we will instead store the unprocessed transitions -// in an array and actually filter them in the passive phase. + var _cache2 = null; -var transitionStack = createCursor(null); + if ( + workInProgress.memoizedState !== null && + workInProgress.memoizedState.cachePool !== null + ) { + _cache2 = workInProgress.memoizedState.cachePool.pool; + } -function peekCacheFromPool() { - // If we're rendering inside a Suspense boundary that is currently hidden, - // we should use the same cache that we used during the previous render, if - // one exists. + if (_cache2 !== _previousCache2) { + // Run passive effects to retain/release the cache. + workInProgress.flags |= Passive$1; + } + } - var cacheResumedFromPreviousRender = resumedCache.current; + popTransition(workInProgress, current); + return null; + } - if (cacheResumedFromPreviousRender !== null) { - return cacheResumedFromPreviousRender; - } // Otherwise, check the root's cache pool. + case CacheComponent: { + { + var _previousCache3 = null; - var root = getWorkInProgressRoot(); - var cacheFromRootCachePool = root.pooledCache; - return cacheFromRootCachePool; -} + if (current !== null) { + _previousCache3 = current.memoizedState.cache; + } -function requestCacheFromPool(renderLanes) { - // Similar to previous function, except if there's not already a cache in the - // pool, we allocate a new one. - var cacheFromPool = peekCacheFromPool(); - - if (cacheFromPool !== null) { - return cacheFromPool; - } // Create a fresh cache and add it to the root cache pool. A cache can have - // multiple owners: - // - A cache pool that lives on the FiberRoot. This is where all fresh caches - // are originally created (TODO: except during refreshes, until we implement - // this correctly). The root takes ownership immediately when the cache is - // created. Conceptually, root.pooledCache is an Option> (owned), - // and the return value of this function is a &Arc (borrowed). - // - One of several fiber types: host root, cache boundary, suspense - // component. These retain and release in the commit phase. - - var root = getWorkInProgressRoot(); - var freshCache = createCache(); - root.pooledCache = freshCache; - retainCache(freshCache); - - if (freshCache !== null) { - root.pooledCacheLanes |= renderLanes; - } - - return freshCache; -} -function pushRootTransition(workInProgress, root, renderLanes) { - if (enableTransitionTracing) { - var rootTransitions = getWorkInProgressTransitions(); - push(transitionStack, rootTransitions, workInProgress); - } -} -function popRootTransition(workInProgress, root, renderLanes) { - if (enableTransitionTracing) { - pop(transitionStack, workInProgress); - } -} -function pushTransition( - offscreenWorkInProgress, - prevCachePool, - newTransitions -) { - { - if (prevCachePool === null) { - push(resumedCache, resumedCache.current, offscreenWorkInProgress); - } else { - push(resumedCache, prevCachePool.pool, offscreenWorkInProgress); - } - } + var _cache3 = workInProgress.memoizedState.cache; - if (enableTransitionTracing) { - if (transitionStack.current === null) { - push(transitionStack, newTransitions, offscreenWorkInProgress); - } else if (newTransitions === null) { - push(transitionStack, transitionStack.current, offscreenWorkInProgress); - } else { - push( - transitionStack, - transitionStack.current.concat(newTransitions), - offscreenWorkInProgress - ); - } - } -} -function popTransition(workInProgress, current) { - if (current !== null) { - if (enableTransitionTracing) { - pop(transitionStack, workInProgress); - } + if (_cache3 !== _previousCache3) { + // Run passive effects to retain/release the cache. + workInProgress.flags |= Passive$1; + } - { - pop(resumedCache, workInProgress); - } - } -} -function getPendingTransitions() { - if (!enableTransitionTracing) { - return null; - } + popCacheProvider(workInProgress); + bubbleProperties(workInProgress); + } - return transitionStack.current; -} -function getSuspendedCache() { - // cache that would have been used to render fresh data during this render, - // if there was any, so that we can resume rendering with the same cache when - // we receive more data. - - var cacheFromPool = peekCacheFromPool(); - - if (cacheFromPool === null) { - return null; - } - - return { - // We must also save the parent, so that when we resume we can detect - // a refresh. - parent: CacheContext._currentValue2, - pool: cacheFromPool - }; -} -function getOffscreenDeferredCache() { - var cacheFromPool = peekCacheFromPool(); - - if (cacheFromPool === null) { - return null; - } - - return { - // We must also store the parent, so that when we resume we can detect - // a refresh. - parent: CacheContext._currentValue2, - pool: cacheFromPool - }; -} + return null; + } -function getSuspenseFallbackChild(fiber) { - return fiber.child.sibling.child; -} + case TracingMarkerComponent: { + if (enableTransitionTracing) { + var _instance4 = workInProgress.stateNode; -var emptyObject = {}; + if (_instance4 !== null) { + popMarkerInstance(workInProgress); + } -function collectScopedNodes(node, fn, scopedNodes) { - { - if (node.tag === HostComponent) { - var type = node.type, - memoizedProps = node.memoizedProps, - stateNode = node.stateNode; - var instance = getPublicInstance(stateNode); + bubbleProperties(workInProgress); + } - if ( - instance !== null && - fn(type, memoizedProps || emptyObject, instance) === true - ) { - scopedNodes.push(instance); + return null; + } } + + throw new Error( + "Unknown unit of work tag (" + + workInProgress.tag + + "). This error is likely caused by a bug in " + + "React. Please file an issue." + ); } - var child = node.child; + function unwindWork(current, workInProgress, renderLanes) { + switch (workInProgress.tag) { + case ClassComponent: { + var Component = workInProgress.type; + + if (isContextProvider(Component)) { + popContext(workInProgress); + } + + var flags = workInProgress.flags; - if (isFiberSuspenseAndTimedOut(node)) { - child = getSuspenseFallbackChild(node); - } + if (flags & ShouldCapture) { + workInProgress.flags = (flags & ~ShouldCapture) | DidCapture; - if (child !== null) { - collectScopedNodesFromChildren(child, fn, scopedNodes); - } - } -} + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } -function collectFirstScopedNode(node, fn) { - { - if (node.tag === HostComponent) { - var type = node.type, - memoizedProps = node.memoizedProps, - stateNode = node.stateNode; - var instance = getPublicInstance(stateNode); + return workInProgress; + } - if (instance !== null && fn(type, memoizedProps, instance) === true) { - return instance; - } - } + return null; + } - var child = node.child; + case HostRoot: { + { + popCacheProvider(workInProgress); + } - if (isFiberSuspenseAndTimedOut(node)) { - child = getSuspenseFallbackChild(node); - } + if (enableTransitionTracing) { + popRootMarkerInstance(workInProgress); + } - if (child !== null) { - return collectFirstScopedNodeFromChildren(child, fn); - } - } + popRootTransition(workInProgress); + popHostContainer(workInProgress); + popTopLevelContextObject(workInProgress); + var _flags = workInProgress.flags; - return null; -} + if ( + (_flags & ShouldCapture) !== NoFlags$1 && + (_flags & DidCapture) === NoFlags$1 + ) { + // There was an error during render that wasn't captured by a suspense + // boundary. Do a second pass on the root to unmount the children. + workInProgress.flags = (_flags & ~ShouldCapture) | DidCapture; + return workInProgress; + } // We unwound to the root without completing it. Exit. -function collectScopedNodesFromChildren(startingChild, fn, scopedNodes) { - var child = startingChild; + return null; + } - while (child !== null) { - collectScopedNodes(child, fn, scopedNodes); - child = child.sibling; - } -} + case HostHoistable: + case HostSingleton: + case HostComponent: { + // TODO: popHydrationState + popHostContext(workInProgress); + return null; + } -function collectFirstScopedNodeFromChildren(startingChild, fn) { - var child = startingChild; + case SuspenseComponent: { + popSuspenseHandler(workInProgress); + var suspenseState = workInProgress.memoizedState; - while (child !== null) { - var scopedNode = collectFirstScopedNode(child, fn); + if (suspenseState !== null && suspenseState.dehydrated !== null) { + if (workInProgress.alternate === null) { + throw new Error( + "Threw in newly mounted dehydrated component. This is likely a bug in " + + "React. Please file an issue." + ); + } + } - if (scopedNode !== null) { - return scopedNode; - } + var _flags2 = workInProgress.flags; - child = child.sibling; - } + if (_flags2 & ShouldCapture) { + workInProgress.flags = (_flags2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. - return null; -} + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } -function collectNearestContextValues(node, context, childContextValues) { - if (node.tag === ContextProvider && node.type._context === context) { - var contextValue = node.memoizedProps.value; - childContextValues.push(contextValue); - } else { - var child = node.child; + return workInProgress; + } - if (isFiberSuspenseAndTimedOut(node)) { - child = getSuspenseFallbackChild(node); - } + return null; + } - if (child !== null) { - collectNearestChildContextValues(child, context, childContextValues); - } - } -} + case SuspenseListComponent: { + popSuspenseListContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been + // caught by a nested boundary. If not, it should bubble through. -function collectNearestChildContextValues( - startingChild, - context, - childContextValues -) { - var child = startingChild; - - while (child !== null) { - collectNearestContextValues(child, context, childContextValues); - child = child.sibling; - } -} + return null; + } -function DO_NOT_USE_queryAllNodes(fn) { - var currentFiber = getInstanceFromScope(); + case HostPortal: + popHostContainer(workInProgress); + return null; - if (currentFiber === null) { - return null; - } + case ContextProvider: + var context = workInProgress.type._context; + popProvider(context, workInProgress); + return null; - var child = currentFiber.child; - var scopedNodes = []; + case OffscreenComponent: + case LegacyHiddenComponent: { + popSuspenseHandler(workInProgress); + popHiddenContext(workInProgress); + popTransition(workInProgress, current); + var _flags3 = workInProgress.flags; - if (child !== null) { - collectScopedNodesFromChildren(child, fn, scopedNodes); - } + if (_flags3 & ShouldCapture) { + workInProgress.flags = (_flags3 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. - return scopedNodes.length === 0 ? null : scopedNodes; -} + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } -function DO_NOT_USE_queryFirstNode(fn) { - var currentFiber = getInstanceFromScope(); + return workInProgress; + } - if (currentFiber === null) { - return null; - } + return null; + } - var child = currentFiber.child; + case CacheComponent: + { + popCacheProvider(workInProgress); + } - if (child !== null) { - return collectFirstScopedNodeFromChildren(child, fn); - } + return null; - return null; -} + case TracingMarkerComponent: + if (enableTransitionTracing) { + if (workInProgress.stateNode !== null) { + popMarkerInstance(workInProgress); + } + } -function containsNode(node) { - var fiber = getInstanceFromNode(); + return null; - while (fiber !== null) { - if (fiber.tag === ScopeComponent && fiber.stateNode === this) { - return true; + default: + return null; + } } - fiber = fiber.return; - } + function unwindInterruptedWork(current, interruptedWork, renderLanes) { + switch (interruptedWork.tag) { + case ClassComponent: { + var childContextTypes = interruptedWork.type.childContextTypes; - return false; -} + if (childContextTypes !== null && childContextTypes !== undefined) { + popContext(interruptedWork); + } -function getChildContextValues(context) { - var currentFiber = getInstanceFromScope(); + break; + } - if (currentFiber === null) { - return []; - } + case HostRoot: { + { + popCacheProvider(interruptedWork); + } - var child = currentFiber.child; - var childContextValues = []; + if (enableTransitionTracing) { + popRootMarkerInstance(interruptedWork); + } - if (child !== null) { - collectNearestChildContextValues(child, context, childContextValues); - } + popRootTransition(interruptedWork); + popHostContainer(interruptedWork); + popTopLevelContextObject(interruptedWork); + break; + } - return childContextValues; -} + case HostHoistable: + case HostSingleton: + case HostComponent: { + popHostContext(interruptedWork); + break; + } -function createScopeInstance() { - return { - DO_NOT_USE_queryAllNodes: DO_NOT_USE_queryAllNodes, - DO_NOT_USE_queryFirstNode: DO_NOT_USE_queryFirstNode, - containsNode: containsNode, - getChildContextValues: getChildContextValues - }; -} + case HostPortal: + popHostContainer(interruptedWork); + break; -function markUpdate(workInProgress) { - // Tag the fiber with an update effect. This turns a Placement into - // a PlacementAndUpdate. - workInProgress.flags |= Update; -} + case SuspenseComponent: + popSuspenseHandler(interruptedWork); + break; -function markRef(workInProgress) { - workInProgress.flags |= Ref | RefStatic; -} + case SuspenseListComponent: + popSuspenseListContext(interruptedWork); + break; -function appendAllChildren( - parent, - workInProgress, - needsVisibilityToggle, - isHidden -) { - { - // We only have the top Fiber that was created but we need recurse down its - // children to find all the terminal nodes. - var node = workInProgress.child; - - while (node !== null) { - if (node.tag === HostComponent || node.tag === HostText) { - appendInitialChild(parent, node.stateNode); - } else if (node.tag === HostPortal || false); - else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } - - if (node === workInProgress) { - return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow + case ContextProvider: + var context = interruptedWork.type._context; + popProvider(context, interruptedWork); + break; - while (node.sibling === null) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - if (node.return === null || node.return === workInProgress) { - return; - } + case OffscreenComponent: + case LegacyHiddenComponent: + popSuspenseHandler(interruptedWork); + popHiddenContext(interruptedWork); + popTransition(interruptedWork, current); + break; - node = node.return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow + case CacheComponent: + { + popCacheProvider(interruptedWork); + } - node.sibling.return = node.return; - node = node.sibling; - } - } -} // An unfortunate fork of appendAllChildren because we have two different parent types. - -function updateHostComponent( - current, - workInProgress, - type, - newProps, - renderLanes -) { - { - // If we have an alternate, that means this is an update and we need to - // schedule a side-effect to do the updates. - var oldProps = current.memoizedProps; - - if (oldProps === newProps) { - // In mutation mode, this is sufficient for a bailout because - // we won't touch this node even if children changed. - return; - } - - markUpdate(workInProgress); - } -} // This function must be called at the very end of the complete phase, because -// it might throw to suspend, and if the resource immediately loads, the work -// loop will resume rendering as if the work-in-progress completed. So it must -// fully complete. -// TODO: This should ideally move to begin phase, but currently the instance is -// not created until the complete phase. For our existing use cases, host nodes -// that suspend don't have children, so it doesn't matter. But that might not -// always be true in the future. - -function preloadInstanceAndSuspendIfNeeded( - workInProgress, - type, - props, - renderLanes -) { - { - // If this flag was set previously, we can remove it. The flag - // represents whether this particular set of props might ever need to - // suspend. The safest thing to do is for maySuspendCommit to always - // return true, but if the renderer is reasonably confident that the - // underlying resource won't be evicted, it can return false as a - // performance optimization. - workInProgress.flags &= ~MaySuspendCommit; - return; - } // Mark this fiber with a flag. This gets set on all host instances -} + break; -function scheduleRetryEffect(workInProgress, retryQueue) { - var wakeables = retryQueue; - - if (wakeables !== null) { - // Schedule an effect to attach a retry listener to the promise. - // TODO: Move to passive phase - workInProgress.flags |= Update; - } else { - // This boundary suspended, but no wakeables were added to the retry - // queue. Check if the renderer suspended commit. If so, this means - // that once the fallback is committed, we can immediately retry - // rendering again, because rendering wasn't actually blocked. Only - // the commit phase. - // TODO: Consider a model where we always schedule an immediate retry, even - // for normal Suspense. That way the retry can partially render up to the - // first thing that suspends. - if (workInProgress.flags & ScheduleRetry) { - var retryLane = // TODO: This check should probably be moved into claimNextRetryLane - // I also suspect that we need some further consolidation of offscreen - // and retry lanes. - workInProgress.tag !== OffscreenComponent - ? claimNextRetryLane() - : OffscreenLane; - workInProgress.lanes = mergeLanes(workInProgress.lanes, retryLane); - } - } -} + case TracingMarkerComponent: + if (enableTransitionTracing) { + var instance = interruptedWork.stateNode; -function updateHostText(current, workInProgress, oldText, newText) { - { - // If the text differs, mark it as an update. All the work in done in commitWork. - if (oldText !== newText) { - markUpdate(workInProgress); - } - } -} + if (instance !== null) { + popMarkerInstance(interruptedWork); + } + } -function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { - switch (renderState.tailMode) { - case "hidden": { - // Any insertions at the end of the tail list after this point - // should be invisible. If there are already mounted boundaries - // anything before them are not considered for collapsing. - // Therefore we need to go through the whole tail to find if - // there are any. - var tailNode = renderState.tail; - var lastTailNode = null; - - while (tailNode !== null) { - if (tailNode.alternate !== null) { - lastTailNode = tailNode; - } - - tailNode = tailNode.sibling; - } // Next we're simply going to delete all insertions after the - // last rendered item. - - if (lastTailNode === null) { - // All remaining items in the tail are insertions. - renderState.tail = null; - } else { - // Detach the insertion after the last node that was already - // inserted. - lastTailNode.sibling = null; + break; } - - break; } - case "collapsed": { - // Any insertions at the end of the tail list after this point - // should be invisible. If there are already mounted boundaries - // anything before them are not considered for collapsing. - // Therefore we need to go through the whole tail to find if - // there are any. - var _tailNode = renderState.tail; - var _lastTailNode = null; + // Provided by www + var ReactFbErrorUtils = require("ReactFbErrorUtils"); - while (_tailNode !== null) { - if (_tailNode.alternate !== null) { - _lastTailNode = _tailNode; - } + if (typeof ReactFbErrorUtils.invokeGuardedCallback !== "function") { + throw new Error( + "Expected ReactFbErrorUtils.invokeGuardedCallback to be a function." + ); + } - _tailNode = _tailNode.sibling; - } // Next we're simply going to delete all insertions after the - // last rendered item. + function invokeGuardedCallbackImpl(name, func, context, a, b, c, d, e, f) { + // This will call `this.onError(err)` if an error was caught. + ReactFbErrorUtils.invokeGuardedCallback.apply(this, arguments); + } - if (_lastTailNode === null) { - // All remaining items in the tail are insertions. - if (!hasRenderedATailFallback && renderState.tail !== null) { - // We suspended during the head. We want to show at least one - // row at the tail. So we'll keep on and cut off the rest. - renderState.tail.sibling = null; - } else { - renderState.tail = null; - } + var hasError = false; + var caughtError = null; // Used by event system to capture/rethrow the first error. + var reporter = { + onError: function (error) { + hasError = true; + caughtError = error; + } + }; + /** + * Call a function while guarding against errors that happens within it. + * Returns an error if it throws, otherwise null. + * + * In production, this is implemented using a try-catch. The reason we don't + * use a try-catch directly is so that we can swap out a different + * implementation in DEV mode. + * + * @param {String} name of the guard to use for logging or debugging + * @param {Function} func The function to invoke + * @param {*} context The context to use when calling the function + * @param {...*} args Arguments for function + */ + + function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) { + hasError = false; + caughtError = null; + invokeGuardedCallbackImpl.apply(reporter, arguments); + } + function hasCaughtError() { + return hasError; + } + function clearCaughtError() { + if (hasError) { + var error = caughtError; + hasError = false; + caughtError = null; + return error; } else { - // Detach the insertion after the last node that was already - // inserted. - _lastTailNode.sibling = null; + 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." + ); } - - break; } - } -} - -function bubbleProperties(completedWork) { - var didBailout = - completedWork.alternate !== null && - completedWork.alternate.child === completedWork.child; - var newChildLanes = NoLanes; - var subtreeFlags = NoFlags$1; - - if (!didBailout) { - // Bubble up the earliest expiration time. - if ((completedWork.mode & ProfileMode) !== NoMode) { - // In profiling mode, resetChildExpirationTime is also used to reset - // profiler durations. - var actualDuration = completedWork.actualDuration; - var treeBaseDuration = completedWork.selfBaseDuration; - var child = completedWork.child; - while (child !== null) { - newChildLanes = mergeLanes( - newChildLanes, - mergeLanes(child.lanes, child.childLanes) - ); - subtreeFlags |= child.subtreeFlags; - subtreeFlags |= child.flags; // When a fiber is cloned, its actualDuration is reset to 0. This value will - // only be updated if work is done on the fiber (i.e. it doesn't bailout). - // When work is done, it should bubble to the parent's actualDuration. If - // the fiber has not been cloned though, (meaning no work was done), then - // this value will reflect the amount of time spent working on a previous - // render. In that case it should not bubble. We determine whether it was - // cloned by comparing the child pointer. - // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + var didWarnAboutUndefinedSnapshotBeforeUpdate = null; - actualDuration += child.actualDuration; // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + { + didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); + } // Used during the commit phase to track the state of the Offscreen component stack. + // Allows us to avoid traversing the return path to find the nearest Offscreen ancestor. + + var offscreenSubtreeIsHidden = false; + var offscreenSubtreeWasHidden = false; + var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; + var nextEffect = null; // Used for Profiling builds to track updaters. + + var inProgressLanes = null; + var inProgressRoot = null; + + function shouldProfile(current) { + return ( + (current.mode & ProfileMode) !== NoMode && + (getExecutionContext() & CommitContext) !== NoContext + ); + } - treeBaseDuration += child.treeBaseDuration; - child = child.sibling; + function reportUncaughtErrorInDEV(error) { + // Wrapping each small part of the commit phase into a guarded + // callback is a bit too slow (https://github.com/facebook/react/pull/21666). + // But we rely on it to surface errors to DEV tools like overlays + // (https://github.com/facebook/react/issues/21712). + // As a compromise, rethrow only caught errors in a guard. + { + invokeGuardedCallback(null, function () { + throw error; + }); + clearCaughtError(); } + } - completedWork.actualDuration = actualDuration; - completedWork.treeBaseDuration = treeBaseDuration; - } else { - var _child = completedWork.child; + function callComponentWillUnmountWithTimer(current, instance) { + instance.props = current.memoizedProps; + instance.state = current.memoizedState; - while (_child !== null) { - newChildLanes = mergeLanes( - newChildLanes, - mergeLanes(_child.lanes, _child.childLanes) - ); - subtreeFlags |= _child.subtreeFlags; - subtreeFlags |= _child.flags; // Update the return pointer so the tree is consistent. This is a code - // smell because it assumes the commit phase is never concurrent with - // the render phase. Will address during refactor to alternate model. + if (shouldProfile(current)) { + try { + startLayoutEffectTimer(); + instance.componentWillUnmount(); + } finally { + recordLayoutEffectDuration(current); + } + } else { + instance.componentWillUnmount(); + } + } // Capture errors so they don't interrupt unmounting. + + function safelyCallComponentWillUnmount( + current, + nearestMountedAncestor, + instance + ) { + try { + callComponentWillUnmountWithTimer(current, instance); + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } + } // Capture errors so they don't interrupt mounting. - _child.return = completedWork; - _child = _child.sibling; + function safelyAttachRef(current, nearestMountedAncestor) { + try { + commitAttachRef(current); + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); } } - completedWork.subtreeFlags |= subtreeFlags; - } else { - // Bubble up the earliest expiration time. - if ((completedWork.mode & ProfileMode) !== NoMode) { - // In profiling mode, resetChildExpirationTime is also used to reset - // profiler durations. - var _treeBaseDuration = completedWork.selfBaseDuration; - var _child2 = completedWork.child; + function safelyDetachRef(current, nearestMountedAncestor) { + var ref = current.ref; + var refCleanup = current.refCleanup; - while (_child2 !== null) { - newChildLanes = mergeLanes( - newChildLanes, - mergeLanes(_child2.lanes, _child2.childLanes) - ); // "Static" flags share the lifetime of the fiber/hook they belong to, - // so we should bubble those up even during a bailout. All the other - // flags have a lifetime only of a single render + commit, so we should - // ignore them. + if (ref !== null) { + if (typeof refCleanup === "function") { + try { + if (shouldProfile(current)) { + try { + startLayoutEffectTimer(); + refCleanup(); + } finally { + recordLayoutEffectDuration(current); + } + } else { + refCleanup(); + } + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } finally { + // `refCleanup` has been called. Nullify all references to it to prevent double invocation. + current.refCleanup = null; + var finishedWork = current.alternate; - subtreeFlags |= _child2.subtreeFlags & StaticMask; - subtreeFlags |= _child2.flags & StaticMask; // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + if (finishedWork != null) { + finishedWork.refCleanup = null; + } + } + } else if (typeof ref === "function") { + var retVal; - _treeBaseDuration += _child2.treeBaseDuration; - _child2 = _child2.sibling; - } + try { + if (shouldProfile(current)) { + try { + startLayoutEffectTimer(); + retVal = ref(null); + } finally { + recordLayoutEffectDuration(current); + } + } else { + retVal = ref(null); + } + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } - completedWork.treeBaseDuration = _treeBaseDuration; - } else { - var _child3 = completedWork.child; + { + if (typeof retVal === "function") { + error( + "Unexpected return value from a callback ref in %s. " + + "A callback ref should not return a function.", + getComponentNameFromFiber(current) + ); + } + } + } else { + // $FlowFixMe[incompatible-use] unable to narrow type to RefObject + ref.current = null; + } + } + } - while (_child3 !== null) { - newChildLanes = mergeLanes( - newChildLanes, - mergeLanes(_child3.lanes, _child3.childLanes) - ); // "Static" flags share the lifetime of the fiber/hook they belong to, - // so we should bubble those up even during a bailout. All the other - // flags have a lifetime only of a single render + commit, so we should - // ignore them. + function safelyCallDestroy(current, nearestMountedAncestor, destroy) { + try { + destroy(); + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } + } - subtreeFlags |= _child3.subtreeFlags & StaticMask; - subtreeFlags |= _child3.flags & StaticMask; // Update the return pointer so the tree is consistent. This is a code - // smell because it assumes the commit phase is never concurrent with - // the render phase. Will address during refactor to alternate model. + var focusedInstanceHandle = null; + var shouldFireAfterActiveInstanceBlur = false; + function commitBeforeMutationEffects(root, firstChild) { + focusedInstanceHandle = prepareForCommit(); + nextEffect = firstChild; + commitBeforeMutationEffects_begin(); // We no longer need to track the active instance fiber - _child3.return = completedWork; - _child3 = _child3.sibling; - } + var shouldFire = shouldFireAfterActiveInstanceBlur; + shouldFireAfterActiveInstanceBlur = false; + focusedInstanceHandle = null; + return shouldFire; } - completedWork.subtreeFlags |= subtreeFlags; - } + function commitBeforeMutationEffects_begin() { + while (nextEffect !== null) { + var fiber = nextEffect; // This phase is only used for beforeActiveInstanceBlur. + // Let's skip the whole loop if it's off. - completedWork.childLanes = newChildLanes; - return didBailout; -} + { + // TODO: Should wrap this in flags check, too, as optimization + var deletions = fiber.deletions; -function completeDehydratedSuspenseBoundary( - current, - workInProgress, - nextState -) { - var wasHydrated = popHydrationState(); - - if (nextState !== null && nextState.dehydrated !== null) { - // We might be inside a hydration state the first time we're picking up this - // Suspense boundary, and also after we've reentered it for further hydration. - if (current === null) { - if (!wasHydrated) { - throw new Error( - "A dehydrated suspense component was completed without a hydrated node. " + - "This is probably a bug in React." - ); + if (deletions !== null) { + for (var i = 0; i < deletions.length; i++) { + var deletion = deletions[i]; + commitBeforeMutationEffectsDeletion(deletion); + } + } + } + + var child = fiber.child; + + if ( + (fiber.subtreeFlags & BeforeMutationMask) !== NoFlags$1 && + child !== null + ) { + child.return = fiber; + nextEffect = child; + } else { + commitBeforeMutationEffects_complete(); + } } + } - prepareToHydrateHostSuspenseInstance(); - bubbleProperties(workInProgress); + function commitBeforeMutationEffects_complete() { + while (nextEffect !== null) { + var fiber = nextEffect; + setCurrentFiber(fiber); - { - if ((workInProgress.mode & ProfileMode) !== NoMode) { - var isTimedOutSuspense = nextState !== null; + try { + commitBeforeMutationEffectsOnFiber(fiber); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } - if (isTimedOutSuspense) { - // Don't count time spent in a timed out Suspense subtree as part of the base duration. - var primaryChildFragment = workInProgress.child; + resetCurrentFiber(); + var sibling = fiber.sibling; - if (primaryChildFragment !== null) { - // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - primaryChildFragment.treeBaseDuration; - } - } + if (sibling !== null) { + sibling.return = fiber.return; + nextEffect = sibling; + return; } - } - return false; - } else { - if ((workInProgress.flags & DidCapture) === NoFlags$1) { - // This boundary did not suspend so it's now hydrated and unsuspended. - workInProgress.memoizedState = null; - } // If nothing suspended, we need to schedule an effect to mark this boundary - // as having hydrated so events know that they're free to be invoked. - // It's also a signal to replay events and the suspense callback. - // If something suspended, schedule an effect to attach retry listeners. - // So we might as well always mark this. + nextEffect = fiber.return; + } + } - workInProgress.flags |= Update; - bubbleProperties(workInProgress); + function commitBeforeMutationEffectsOnFiber(finishedWork) { + var current = finishedWork.alternate; + var flags = finishedWork.flags; { - if ((workInProgress.mode & ProfileMode) !== NoMode) { - var _isTimedOutSuspense = nextState !== null; + if ( + !shouldFireAfterActiveInstanceBlur && + focusedInstanceHandle !== null + ) { + // Check to see if the focused element was inside of a hidden (Suspense) subtree. + // TODO: Move this out of the hot path using a dedicated effect tag. + if ( + finishedWork.tag === SuspenseComponent && + isSuspenseBoundaryBeingHidden(current, finishedWork) && // $FlowFixMe[incompatible-call] found when upgrading Flow + doesFiberContain(finishedWork, focusedInstanceHandle) + ) { + shouldFireAfterActiveInstanceBlur = true; + } + } + } - if (_isTimedOutSuspense) { - // Don't count time spent in a timed out Suspense subtree as part of the base duration. - var _primaryChildFragment = workInProgress.child; + if ((flags & Snapshot) !== NoFlags$1) { + setCurrentFiber(finishedWork); + } - if (_primaryChildFragment !== null) { - // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - _primaryChildFragment.treeBaseDuration; + switch (finishedWork.tag) { + case FunctionComponent: { + { + if ((flags & Update) !== NoFlags$1) { + commitUseEffectEventMount(finishedWork); } } + + break; } - } - return false; - } - } else { - // Successfully completed this tree. If this was a forced client render, - // there may have been recoverable errors during first hydration - // attempt. If so, add them to a queue so we can log them in the - // commit phase. - upgradeHydrationErrorsToRecoverable(); // Fall through to normal Suspense path + case ForwardRef: + case SimpleMemoComponent: { + break; + } - return true; - } -} + case ClassComponent: { + if ((flags & Snapshot) !== NoFlags$1) { + if (current !== null) { + var prevProps = current.memoizedProps; + var prevState = current.memoizedState; + var instance = finishedWork.stateNode; // We could update instance props and state here, + // but instead we rely on them being set during last render. + // TODO: revisit this when we implement resuming. -function completeWork(current, workInProgress, renderLanes) { - var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing - - switch (workInProgress.tag) { - case IndeterminateComponent: - case LazyComponent: - case SimpleMemoComponent: - case FunctionComponent: - case ForwardRef: - case Fragment: - case Mode: - case Profiler: - case ContextConsumer: - case MemoComponent: - bubbleProperties(workInProgress); - return null; + { + if ( + finishedWork.type === finishedWork.elementType && + !didWarnAboutReassigningProps + ) { + if (instance.props !== finishedWork.memoizedProps) { + 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" + ); + } - case ClassComponent: { - var Component = workInProgress.type; + if (instance.state !== finishedWork.memoizedState) { + 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" + ); + } + } + } - if (isContextProvider(Component)) { - popContext(workInProgress); - } + var snapshot = instance.getSnapshotBeforeUpdate( + finishedWork.elementType === finishedWork.type + ? prevProps + : resolveDefaultProps(finishedWork.type, prevProps), + prevState + ); - bubbleProperties(workInProgress); - return null; - } + { + var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate; + + if ( + snapshot === undefined && + !didWarnSet.has(finishedWork.type) + ) { + didWarnSet.add(finishedWork.type); - case HostRoot: { - var fiberRoot = workInProgress.stateNode; + error( + "%s.getSnapshotBeforeUpdate(): A snapshot value (or null) " + + "must be returned. You have returned undefined.", + getComponentNameFromFiber(finishedWork) + ); + } + } - if (enableTransitionTracing) { - var transitions = getWorkInProgressTransitions(); // We set the Passive flag here because if there are new transitions, - // we will need to schedule callbacks and process the transitions, - // which we do in the passive phase + instance.__reactInternalSnapshotBeforeUpdate = snapshot; + } + } - if (transitions !== null) { - workInProgress.flags |= Passive$1; + break; } - } - - { - var previousCache = null; - if (current !== null) { - previousCache = current.memoizedState.cache; + case HostRoot: { + break; } - var cache = workInProgress.memoizedState.cache; + case HostComponent: + case HostHoistable: + case HostSingleton: + case HostText: + case HostPortal: + case IncompleteClassComponent: + // Nothing to do for these component types + break; - if (cache !== previousCache) { - // Run passive effects to retain/release the cache. - workInProgress.flags |= Passive$1; + default: { + if ((flags & Snapshot) !== NoFlags$1) { + 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." + ); + } } + } - popCacheProvider(workInProgress); + if ((flags & Snapshot) !== NoFlags$1) { + resetCurrentFiber(); } + } - if (enableTransitionTracing) { - popRootMarkerInstance(workInProgress); + function commitBeforeMutationEffectsDeletion(deletion) { + { + // TODO (effects) It would be nice to avoid calling doesFiberContain() + // Maybe we can repurpose one of the subtreeFlags positions for this instead? + // Use it to store which part of the tree the focused instance is in? + // This assumes we can safely determine that instance during the "render" phase. + if (doesFiberContain(deletion, focusedInstanceHandle)) { + shouldFireAfterActiveInstanceBlur = true; + } } + } + + function commitHookEffectListUnmount( + flags, + finishedWork, + nearestMountedAncestor + ) { + var updateQueue = finishedWork.updateQueue; + var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; - popRootTransition(workInProgress); - popHostContainer(workInProgress); - popTopLevelContextObject(workInProgress); + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; - if (fiberRoot.pendingContext) { - fiberRoot.context = fiberRoot.pendingContext; - fiberRoot.pendingContext = null; - } + do { + if ((effect.tag & flags) === flags) { + // Unmount + var inst = effect.inst; + var destroy = inst.destroy; + + if (destroy !== undefined) { + inst.destroy = undefined; + + if (enableSchedulingProfiler) { + if ((flags & Passive) !== NoFlags) { + markComponentPassiveEffectUnmountStarted(finishedWork); + } else if ((flags & Layout) !== NoFlags) { + markComponentLayoutEffectUnmountStarted(finishedWork); + } + } - if (current === null || current.child === null) { - // If we hydrated, pop so that we can delete any remaining children - // that weren't hydrated. - var wasHydrated = popHydrationState(); + { + if ((flags & Insertion) !== NoFlags) { + setIsRunningInsertionEffect(true); + } + } - if (wasHydrated) { - // If we hydrated, then we'll need to schedule an update for - // the commit side-effects on the root. - markUpdate(workInProgress); - } else { - if (current !== null) { - var prevState = current.memoizedState; + safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy); - if ( - // Check if this is a client root - !prevState.isDehydrated || // Check if we reverted to client rendering (e.g. due to an error) - (workInProgress.flags & ForceClientRender) !== NoFlags$1 - ) { - // Schedule an effect to clear this container at the start of the - // next commit. This handles the case of React rendering into a - // container with previous children. It's also safe to do for - // updates too, because current.child would only be null if the - // previous render was null (so the container would already - // be empty). - workInProgress.flags |= Snapshot; // If this was a forced client render, there may have been - // recoverable errors during first hydration attempt. If so, add - // them to a queue so we can log them in the commit phase. + { + if ((flags & Insertion) !== NoFlags) { + setIsRunningInsertionEffect(false); + } + } - upgradeHydrationErrorsToRecoverable(); + if (enableSchedulingProfiler) { + if ((flags & Passive) !== NoFlags) { + markComponentPassiveEffectUnmountStopped(); + } else if ((flags & Layout) !== NoFlags) { + markComponentLayoutEffectUnmountStopped(); + } + } } } - } - } - bubbleProperties(workInProgress); - if (enableTransitionTracing) { - if ((workInProgress.subtreeFlags & Visibility) !== NoFlags$1) { - // If any of our suspense children toggle visibility, this means that - // the pending boundaries array needs to be updated, which we only - // do in the passive phase. - workInProgress.flags |= Passive$1; - } + effect = effect.next; + } while (effect !== firstEffect); } - - return null; } - case HostHoistable: + function commitHookEffectListMount(flags, finishedWork) { + var updateQueue = finishedWork.updateQueue; + var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; - case HostSingleton: + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; - case HostComponent: { - popHostContext(workInProgress); - var _type2 = workInProgress.type; + do { + if ((effect.tag & flags) === flags) { + if (enableSchedulingProfiler) { + if ((flags & Passive) !== NoFlags) { + markComponentPassiveEffectMountStarted(finishedWork); + } else if ((flags & Layout) !== NoFlags) { + markComponentLayoutEffectMountStarted(finishedWork); + } + } // Mount - if (current !== null && workInProgress.stateNode != null) { - updateHostComponent(current, workInProgress, _type2, newProps); + var create = effect.create; - if (current.ref !== workInProgress.ref) { - markRef(workInProgress); - } - } else { - if (!newProps) { - if (workInProgress.stateNode === null) { - 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." - ); - } // This can happen when we abort work. + { + if ((flags & Insertion) !== NoFlags) { + setIsRunningInsertionEffect(true); + } + } - bubbleProperties(workInProgress); - return null; - } + var inst = effect.inst; + var destroy = create(); + inst.destroy = destroy; - getHostContext(); // TODO: Move createInstance to beginWork and keep it on a context - // "stack" as the parent. Then append children as we go in beginWork - // or completeWork depending on whether we want to add them top->down or - // bottom->up. Top->down is faster in IE11. + { + if ((flags & Insertion) !== NoFlags) { + setIsRunningInsertionEffect(false); + } + } + + if (enableSchedulingProfiler) { + if ((flags & Passive) !== NoFlags) { + markComponentPassiveEffectMountStopped(); + } else if ((flags & Layout) !== NoFlags) { + markComponentLayoutEffectMountStopped(); + } + } - var _wasHydrated2 = popHydrationState(); + { + if (destroy !== undefined && typeof destroy !== "function") { + var hookName = void 0; - if (_wasHydrated2) { - // TODO: Move this and createInstance step into the beginPhase - // to consolidate. - prepareToHydrateHostInstance(); - } else { - getRootHostContainer(); + if ((effect.tag & Layout) !== NoFlags$1) { + hookName = "useLayoutEffect"; + } else if ((effect.tag & Insertion) !== NoFlags$1) { + hookName = "useInsertionEffect"; + } else { + hookName = "useEffect"; + } - var _instance3 = createInstance(_type2, newProps); // TODO: For persistent renderers, we should pass children as part - // of the initial instance creation + var addendum = void 0; + + if (destroy === null) { + addendum = + " You returned null. If your effect does not require clean " + + "up, return undefined (or nothing)."; + } else if (typeof destroy.then === "function") { + 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"; + } else { + addendum = " You returned: " + destroy; + } - appendAllChildren(_instance3, workInProgress); - workInProgress.stateNode = _instance3; // Certain renderers require commit-time effects for initial mount. - } + error( + "%s must not return anything besides a function, " + + "which is used for clean-up.%s", + hookName, + addendum + ); + } + } + } - if (workInProgress.ref !== null) { - // If there is a ref on a host node we need to schedule a callback - markRef(workInProgress); - } + effect = effect.next; + } while (effect !== firstEffect); } + } - bubbleProperties(workInProgress); // This must come at the very end of the complete phase, because it might - // throw to suspend, and if the resource immediately loads, the work loop - // will resume rendering as if the work-in-progress completed. So it must - // fully complete. + function commitUseEffectEventMount(finishedWork) { + var updateQueue = finishedWork.updateQueue; + var eventPayloads = updateQueue !== null ? updateQueue.events : null; - preloadInstanceAndSuspendIfNeeded(workInProgress); - return null; + if (eventPayloads !== null) { + for (var ii = 0; ii < eventPayloads.length; ii++) { + var _eventPayloads$ii = eventPayloads[ii], + ref = _eventPayloads$ii.ref, + nextImpl = _eventPayloads$ii.nextImpl; + ref.impl = nextImpl; + } + } } - case HostText: { - var newText = newProps; - - if (current && workInProgress.stateNode != null) { - var oldText = current.memoizedProps; // If we have an alternate, that means this is an update and we need - // to schedule a side-effect to do the updates. + function commitPassiveEffectDurations(finishedRoot, finishedWork) { + if (getExecutionContext() & CommitContext) { + // Only Profilers with work in their subtree will have an Update effect scheduled. + if ((finishedWork.flags & Update) !== NoFlags$1) { + switch (finishedWork.tag) { + case Profiler: { + var passiveEffectDuration = + finishedWork.stateNode.passiveEffectDuration; + var _finishedWork$memoize = finishedWork.memoizedProps, + id = _finishedWork$memoize.id, + onPostCommit = _finishedWork$memoize.onPostCommit; // This value will still reflect the previous commit phase. + // It does not get reset until the start of the next commit phase. - updateHostText(current, workInProgress, oldText, newText); - } else { - if (typeof newText !== "string") { - if (workInProgress.stateNode === null) { - 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." - ); - } // This can happen when we abort work. - } + var commitTime = getCommitTime(); + var phase = finishedWork.alternate === null ? "mount" : "update"; - getRootHostContainer(); + { + if (isCurrentUpdateNested()) { + phase = "nested-update"; + } + } - getHostContext(); + if (typeof onPostCommit === "function") { + onPostCommit(id, phase, passiveEffectDuration, commitTime); + } // Bubble times to the next nearest ancestor Profiler. + // After we process that Profiler, we'll bubble further up. + + var parentFiber = finishedWork.return; + + outer: while (parentFiber !== null) { + switch (parentFiber.tag) { + case HostRoot: + var root = parentFiber.stateNode; + root.passiveEffectDuration += passiveEffectDuration; + break outer; + + case Profiler: + var parentStateNode = parentFiber.stateNode; + parentStateNode.passiveEffectDuration += + passiveEffectDuration; + break outer; + } - var _wasHydrated3 = popHydrationState(); + parentFiber = parentFiber.return; + } - if (_wasHydrated3) { - if (prepareToHydrateHostTextInstance()) { - markUpdate(workInProgress); + break; + } } - } else { - workInProgress.stateNode = createTextInstance(newText); } } - - bubbleProperties(workInProgress); - return null; } - case SuspenseComponent: { - popSuspenseHandler(workInProgress); - var nextState = workInProgress.memoizedState; // Special path for dehydrated boundaries. We may eventually move this - // to its own fiber type so that we can add other kinds of hydration - // boundaries that aren't associated with a Suspense tree. In anticipation - // of such a refactor, all the hydration logic is contained in - // this branch. - - if ( - current === null || - (current.memoizedState !== null && - current.memoizedState.dehydrated !== null) - ) { - var fallthroughToNormalSuspensePath = - completeDehydratedSuspenseBoundary( - current, - workInProgress, - nextState - ); - - if (!fallthroughToNormalSuspensePath) { - if (workInProgress.flags & ForceClientRender) { - // Special case. There were remaining unhydrated nodes. We treat - // this as a mismatch. Revert to client rendering. - return workInProgress; - } else { - // Did not finish hydrating, either because this is the initial - // render or because something suspended. - return null; - } - } // Continue with the normal Suspense path. - } - - if ((workInProgress.flags & DidCapture) !== NoFlags$1) { - // Something suspended. Re-render with the fallback children. - workInProgress.lanes = renderLanes; // Do not reset the effect list. - - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); - } // Don't bubble properties in this case. + function commitHookLayoutEffects(finishedWork, hookFlags) { + // At this point layout effects have already been destroyed (during mutation phase). + // This is done to prevent sibling component effects from interfering with each other, + // e.g. a destroy function in one component should never override a ref set + // by a create function in another component during the same commit. + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + commitHookEffectListMount(hookFlags, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } - return workInProgress; + recordLayoutEffectDuration(finishedWork); + } else { + try { + commitHookEffectListMount(hookFlags, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } } + } - var nextDidTimeout = nextState !== null; - var prevDidTimeout = current !== null && current.memoizedState !== null; + function commitClassLayoutLifecycles(finishedWork, current) { + var instance = finishedWork.stateNode; - if (nextDidTimeout) { - var offscreenFiber = workInProgress.child; - var _previousCache = null; + if (current === null) { + // We could update instance props and state here, + // but instead we rely on them being set during last render. + // TODO: revisit this when we implement resuming. + { + if ( + finishedWork.type === finishedWork.elementType && + !didWarnAboutReassigningProps + ) { + if (instance.props !== finishedWork.memoizedProps) { + 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" + ); + } - if ( - offscreenFiber.alternate !== null && - offscreenFiber.alternate.memoizedState !== null && - offscreenFiber.alternate.memoizedState.cachePool !== null - ) { - _previousCache = - offscreenFiber.alternate.memoizedState.cachePool.pool; + if (instance.state !== finishedWork.memoizedState) { + 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" + ); + } + } } - var _cache = null; + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + instance.componentDidMount(); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } - if ( - offscreenFiber.memoizedState !== null && - offscreenFiber.memoizedState.cachePool !== null - ) { - _cache = offscreenFiber.memoizedState.cachePool.pool; + recordLayoutEffectDuration(finishedWork); + } else { + try { + instance.componentDidMount(); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } } + } else { + var prevProps = + finishedWork.elementType === finishedWork.type + ? current.memoizedProps + : resolveDefaultProps(finishedWork.type, current.memoizedProps); + var prevState = current.memoizedState; // We could update instance props and state here, + // but instead we rely on them being set during last render. + // TODO: revisit this when we implement resuming. - if (_cache !== _previousCache) { - // Run passive effects to retain/release the cache. - offscreenFiber.flags |= Passive$1; + { + if ( + finishedWork.type === finishedWork.elementType && + !didWarnAboutReassigningProps + ) { + if (instance.props !== finishedWork.memoizedProps) { + 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" + ); + } + + if (instance.state !== finishedWork.memoizedState) { + 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" + ); + } + } } - } // If the suspended state of the boundary changes, we need to schedule - // a passive effect, which is when we process the transitions - if (nextDidTimeout !== prevDidTimeout) { - if (enableTransitionTracing) { - var _offscreenFiber = workInProgress.child; - _offscreenFiber.flags |= Passive$1; - } // If the suspended state of the boundary changes, we need to schedule - // an effect to toggle the subtree's visibility. When we switch from - // fallback -> primary, the inner Offscreen fiber schedules this effect - // as part of its normal complete phase. But when we switch from - // primary -> fallback, the inner Offscreen fiber does not have a complete - // phase. So we need to schedule its effect here. - // - // We also use this flag to connect/disconnect the effects, but the same - // logic applies: when re-connecting, the Offscreen fiber's complete - // phase will handle scheduling the effect. It's only when the fallback - // is active that we have to do anything special. + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + instance.componentDidUpdate( + prevProps, + prevState, + instance.__reactInternalSnapshotBeforeUpdate + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } - if (nextDidTimeout) { - var _offscreenFiber2 = workInProgress.child; - _offscreenFiber2.flags |= Visibility; + recordLayoutEffectDuration(finishedWork); + } else { + try { + instance.componentDidUpdate( + prevProps, + prevState, + instance.__reactInternalSnapshotBeforeUpdate + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } } } + } - var retryQueue = workInProgress.updateQueue; - scheduleRetryEffect(workInProgress, retryQueue); - - if ( - workInProgress.updateQueue !== null && - workInProgress.memoizedProps.suspenseCallback != null - ) { - // Always notify the callback - // TODO: Move to passive phase - workInProgress.flags |= Update; - } + function commitClassCallbacks(finishedWork) { + // TODO: I think this is now always non-null by the time it reaches the + // commit phase. Consider removing the type check. + var updateQueue = finishedWork.updateQueue; - bubbleProperties(workInProgress); + if (updateQueue !== null) { + var instance = finishedWork.stateNode; - { - if ((workInProgress.mode & ProfileMode) !== NoMode) { - if (nextDidTimeout) { - // Don't count time spent in a timed out Suspense subtree as part of the base duration. - var primaryChildFragment = workInProgress.child; + { + if ( + finishedWork.type === finishedWork.elementType && + !didWarnAboutReassigningProps + ) { + if (instance.props !== finishedWork.memoizedProps) { + 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" + ); + } - if (primaryChildFragment !== null) { - // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - primaryChildFragment.treeBaseDuration; + if (instance.state !== finishedWork.memoizedState) { + 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" + ); } } + } // We could update instance props and state here, + // but instead we rely on them being set during last render. + // TODO: revisit this when we implement resuming. + + try { + commitCallbacks(updateQueue, instance); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } } - - return null; } - case HostPortal: - popHostContainer(workInProgress); - - bubbleProperties(workInProgress); - return null; + function commitHostComponentMount(finishedWork) { + var type = finishedWork.type; + var props = finishedWork.memoizedProps; + var instance = finishedWork.stateNode; - case ContextProvider: - // Pop provider fiber - var context = workInProgress.type._context; - popProvider(context, workInProgress); - bubbleProperties(workInProgress); - return null; + try { + commitMount(instance, type, props, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } - case IncompleteClassComponent: { - // Same as class component case. I put it down here so that the tags are - // sequential to ensure this switch is compiled to a jump table. - var _Component = workInProgress.type; + function commitProfilerUpdate(finishedWork, current) { + if (getExecutionContext() & CommitContext) { + try { + var _finishedWork$memoize2 = finishedWork.memoizedProps, + onCommit = _finishedWork$memoize2.onCommit, + onRender = _finishedWork$memoize2.onRender; + var effectDuration = finishedWork.stateNode.effectDuration; + var commitTime = getCommitTime(); + var phase = current === null ? "mount" : "update"; - if (isContextProvider(_Component)) { - popContext(workInProgress); - } + if (enableProfilerNestedUpdatePhase) { + if (isCurrentUpdateNested()) { + phase = "nested-update"; + } + } - bubbleProperties(workInProgress); - return null; - } + if (typeof onRender === "function") { + onRender( + finishedWork.memoizedProps.id, + phase, + finishedWork.actualDuration, + finishedWork.treeBaseDuration, + finishedWork.actualStartTime, + commitTime + ); + } - case SuspenseListComponent: { - popSuspenseListContext(workInProgress); - var renderState = workInProgress.memoizedState; + if (enableProfilerCommitHooks) { + if (typeof onCommit === "function") { + onCommit( + finishedWork.memoizedProps.id, + phase, + effectDuration, + commitTime + ); + } // Schedule a passive effect for this Profiler to call onPostCommit hooks. + // This effect should be scheduled even if there is no onPostCommit callback for this Profiler, + // because the effect is also where times bubble to parent Profilers. + + enqueuePendingPassiveProfilerEffect(finishedWork); // Propagate layout effect durations to the next nearest Profiler ancestor. + // Do not reset these values until the next render so DevTools has a chance to read them first. + + var parentFiber = finishedWork.return; + + outer: while (parentFiber !== null) { + switch (parentFiber.tag) { + case HostRoot: + var root = parentFiber.stateNode; + root.effectDuration += effectDuration; + break outer; + + case Profiler: + var parentStateNode = parentFiber.stateNode; + parentStateNode.effectDuration += effectDuration; + break outer; + } - if (renderState === null) { - // We're running in the default, "independent" mode. - // We don't do anything in this mode. - bubbleProperties(workInProgress); - return null; + parentFiber = parentFiber.return; + } + } + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } } + } - var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags$1; - var renderedTail = renderState.rendering; - - if (renderedTail === null) { - // We just rendered the head. - if (!didSuspendAlready) { - // This is the first pass. We need to figure out if anything is still - // suspended in the rendered set. - // If new content unsuspended, but there's still some content that - // didn't. Then we need to do a second pass that forces everything - // to keep showing their fallbacks. - // We might be suspended if something in this render pass suspended, or - // something in the previous committed pass suspended. Otherwise, - // there's no chance so we can skip the expensive call to - // findFirstSuspended. - var cannotBeSuspended = - renderHasNotSuspendedYet() && - (current === null || (current.flags & DidCapture) === NoFlags$1); - - if (!cannotBeSuspended) { - var row = workInProgress.child; - - while (row !== null) { - var suspended = findFirstSuspended(row); + function commitLayoutEffectOnFiber( + finishedRoot, + current, + finishedWork, + committedLanes + ) { + // When updating this function, also update reappearLayoutEffects, which does + // most of the same things when an offscreen tree goes from hidden -> visible. + var flags = finishedWork.flags; - if (suspended !== null) { - didSuspendAlready = true; - workInProgress.flags |= DidCapture; - cutOffTailIfNeeded(renderState, false); // If this is a newly suspended tree, it might not get committed as - // part of the second pass. In that case nothing will subscribe to - // its thenables. Instead, we'll transfer its thenables to the - // SuspenseList so that it can retry if they resolve. - // There might be multiple of these in the list but since we're - // going to wait for all of them anyway, it doesn't really matter - // which ones gets to ping. In theory we could get clever and keep - // track of how many dependencies remain but it gets tricky because - // in the meantime, we can add/remove/change items and dependencies. - // We might bail out of the loop before finding any but that - // doesn't matter since that means that the other boundaries that - // we did find already has their listeners attached. - - var _retryQueue = suspended.updateQueue; - workInProgress.updateQueue = _retryQueue; - scheduleRetryEffect(workInProgress, _retryQueue); // Rerender the whole list, but this time, we'll force fallbacks - // to stay in place. - // Reset the effect flags before doing the second pass since that's now invalid. - // Reset the child fibers to their original state. - - workInProgress.subtreeFlags = NoFlags$1; - resetChildFibers(workInProgress, renderLanes); // Set up the Suspense List Context to force suspense and - // immediately rerender the children. - - pushSuspenseListContext( - workInProgress, - setShallowSuspenseListContext( - suspenseStackCursor.current, - ForceSuspenseFallback - ) - ); // Don't bubble properties in this case. - - return workInProgress.child; - } + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - row = row.sibling; - } + if (flags & Update) { + commitHookLayoutEffects(finishedWork, Layout | HasEffect); } - if (renderState.tail !== null && now$1() > getRenderTargetTime()) { - // We have already passed our CPU deadline but we still have rows - // left in the tail. We'll just give up further attempts to render - // the main content and only render fallbacks. - workInProgress.flags |= DidCapture; - didSuspendAlready = true; - cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this - // to get it started back up to attempt the next item. While in terms - // of priority this work has the same priority as this current render, - // it's not part of the same transition once the transition has - // committed. If it's sync, we still want to yield so that it can be - // painted. Conceptually, this is really the same as pinging. - // We can use any RetryLane even if it's the one currently rendering - // since we're leaving it behind on this node. - - workInProgress.lanes = SomeRetryLane; - } - } else { - cutOffTailIfNeeded(renderState, false); - } // Next we're going to render the tail. - } else { - // Append the rendered row to the child list. - if (!didSuspendAlready) { - var _suspended = findFirstSuspended(renderedTail); + break; + } - if (_suspended !== null) { - workInProgress.flags |= DidCapture; - didSuspendAlready = true; // Ensure we transfer the update queue to the parent so that it doesn't - // get lost if this row ends up dropped during a second pass. + case ClassComponent: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - var _retryQueue2 = _suspended.updateQueue; - workInProgress.updateQueue = _retryQueue2; - scheduleRetryEffect(workInProgress, _retryQueue2); - cutOffTailIfNeeded(renderState, true); // This might have been modified. + if (flags & Update) { + commitClassLayoutLifecycles(finishedWork, current); + } - if ( - renderState.tail === null && - renderState.tailMode === "hidden" && - !renderedTail.alternate && - !getIsHydrating() // We don't cut it if we're hydrating. - ) { - // We're done. - bubbleProperties(workInProgress); - return null; - } - } else if ( - // The time it took to render last row is greater than the remaining - // time we have to render. So rendering one more row would likely - // exceed it. - now$1() * 2 - renderState.renderingStartTime > - getRenderTargetTime() && - renderLanes !== OffscreenLane - ) { - // We have now passed our CPU deadline and we'll just give up further - // attempts to render the main content and only render fallbacks. - // The assumption is that this is usually faster. - workInProgress.flags |= DidCapture; - didSuspendAlready = true; - cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this - // to get it started back up to attempt the next item. While in terms - // of priority this work has the same priority as this current render, - // it's not part of the same transition once the transition has - // committed. If it's sync, we still want to yield so that it can be - // painted. Conceptually, this is really the same as pinging. - // We can use any RetryLane even if it's the one currently rendering - // since we're leaving it behind on this node. - - workInProgress.lanes = SomeRetryLane; - } - } - - if (renderState.isBackwards) { - // The effect list of the backwards tail will have been added - // to the end. This breaks the guarantee that life-cycles fire in - // sibling order but that isn't a strong guarantee promised by React. - // Especially since these might also just pop in during future commits. - // Append to the beginning of the list. - renderedTail.sibling = workInProgress.child; - workInProgress.child = renderedTail; - } else { - var previousSibling = renderState.last; + if (flags & Callback) { + commitClassCallbacks(finishedWork); + } - if (previousSibling !== null) { - previousSibling.sibling = renderedTail; - } else { - workInProgress.child = renderedTail; + if (flags & Ref) { + safelyAttachRef(finishedWork, finishedWork.return); } - renderState.last = renderedTail; + break; } - } - if (renderState.tail !== null) { - // We still have tail rows to render. - // Pop a row. - var next = renderState.tail; - renderState.rendering = next; - renderState.tail = next.sibling; - renderState.renderingStartTime = now$1(); - next.sibling = null; // Restore the context. - // TODO: We can probably just avoid popping it instead and only - // setting it the first time we go from not suspended to suspended. + case HostRoot: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + + if (flags & Callback) { + // TODO: I think this is now always non-null by the time it reaches the + // commit phase. Consider removing the type check. + var updateQueue = finishedWork.updateQueue; + + if (updateQueue !== null) { + var instance = null; + + if (finishedWork.child !== null) { + switch (finishedWork.child.tag) { + case HostSingleton: + case HostComponent: + instance = getPublicInstance(finishedWork.child.stateNode); + break; + + case ClassComponent: + instance = finishedWork.child.stateNode; + break; + } + } - var suspenseContext = suspenseStackCursor.current; + try { + commitCallbacks(updateQueue, instance); + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } + } + } - if (didSuspendAlready) { - suspenseContext = setShallowSuspenseListContext( - suspenseContext, - ForceSuspenseFallback - ); - } else { - suspenseContext = - setDefaultShallowSuspenseListContext(suspenseContext); + break; } - pushSuspenseListContext(workInProgress, suspenseContext); // Do a pass over the next row. - // Don't bubble properties in this case. - - return next; - } - - bubbleProperties(workInProgress); - return null; - } + case HostHoistable: - case ScopeComponent: { - { - if (current === null) { - var scopeInstance = createScopeInstance(); - workInProgress.stateNode = scopeInstance; - prepareScopeUpdate(); + case HostSingleton: + case HostComponent: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); // Renderers may schedule work to be done after host components are mounted + // (eg DOM renderer may schedule auto-focus for inputs and form controls). + // These effects should only be committed when components are first mounted, + // aka when there is no current/alternate. - if (workInProgress.ref !== null) { - markRef(workInProgress); - markUpdate(workInProgress); - } - } else { - if (workInProgress.ref !== null) { - markUpdate(workInProgress); + if (current === null && flags & Update) { + commitHostComponentMount(finishedWork); } - if (current.ref !== workInProgress.ref) { - markRef(workInProgress); + if (flags & Ref) { + safelyAttachRef(finishedWork, finishedWork.return); } - } - bubbleProperties(workInProgress); - return null; - } - } - - case OffscreenComponent: - case LegacyHiddenComponent: { - popSuspenseHandler(workInProgress); - popHiddenContext(workInProgress); - var _nextState = workInProgress.memoizedState; - var nextIsHidden = _nextState !== null; // Schedule a Visibility effect if the visibility has changed + break; + } - if (workInProgress.tag === LegacyHiddenComponent); - else { - if (current !== null) { - var _prevState = current.memoizedState; - var prevIsHidden = _prevState !== null; + case Profiler: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); // TODO: Should this fire inside an offscreen tree? Or should it wait to + // fire when the tree becomes visible again. - if (prevIsHidden !== nextIsHidden) { - workInProgress.flags |= Visibility; - } - } else { - // On initial mount, we only need a Visibility effect if the tree - // is hidden. - if (nextIsHidden) { - workInProgress.flags |= Visibility; + if (flags & Update) { + commitProfilerUpdate(finishedWork, current); } + + break; } - } - if (!nextIsHidden || (workInProgress.mode & ConcurrentMode) === NoMode) { - bubbleProperties(workInProgress); - } else { - // Don't bubble properties for hidden children unless we're rendering - // at offscreen priority. - if ( - includesSomeLane(renderLanes, OffscreenLane) && // Also don't bubble if the tree suspended - (workInProgress.flags & DidCapture) === NoLanes - ) { - bubbleProperties(workInProgress); // Check if there was an insertion or update in the hidden subtree. - // If so, we need to hide those nodes in the commit phase, so - // schedule a visibility effect. + case SuspenseComponent: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - if ( - workInProgress.tag !== LegacyHiddenComponent && - workInProgress.subtreeFlags & (Placement | Update) - ) { - workInProgress.flags |= Visibility; - } + break; } - } - var offscreenQueue = workInProgress.updateQueue; + case OffscreenComponent: { + var isModernRoot = (finishedWork.mode & ConcurrentMode) !== NoMode; - if (offscreenQueue !== null) { - var _retryQueue3 = offscreenQueue.retryQueue; - scheduleRetryEffect(workInProgress, _retryQueue3); - } + if (isModernRoot) { + var isHidden = finishedWork.memoizedState !== null; + var newOffscreenSubtreeIsHidden = + isHidden || offscreenSubtreeIsHidden; - { - var _previousCache2 = null; + if (newOffscreenSubtreeIsHidden); + else { + // The Offscreen tree is visible. + var wasHidden = + current !== null && current.memoizedState !== null; + var newOffscreenSubtreeWasHidden = + wasHidden || offscreenSubtreeWasHidden; + var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden; + var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; + offscreenSubtreeIsHidden = newOffscreenSubtreeIsHidden; + offscreenSubtreeWasHidden = newOffscreenSubtreeWasHidden; + + if (offscreenSubtreeWasHidden && !prevOffscreenSubtreeWasHidden) { + // This is the root of a reappearing boundary. As we continue + // traversing the layout effects, we must also re-mount layout + // effects that were unmounted when the Offscreen subtree was + // hidden. So this is a superset of the normal commitLayoutEffects. + var includeWorkInProgressEffects = + (finishedWork.subtreeFlags & LayoutMask) !== NoFlags$1; + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); + } else { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + } - if ( - current !== null && - current.memoizedState !== null && - current.memoizedState.cachePool !== null - ) { - _previousCache2 = current.memoizedState.cachePool.pool; - } + offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; + offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; + } + } else { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + } - var _cache2 = null; + if (flags & Ref) { + var props = finishedWork.memoizedProps; - if ( - workInProgress.memoizedState !== null && - workInProgress.memoizedState.cachePool !== null - ) { - _cache2 = workInProgress.memoizedState.cachePool.pool; + if (props.mode === "manual") { + safelyAttachRef(finishedWork, finishedWork.return); + } else { + safelyDetachRef(finishedWork, finishedWork.return); + } + } + + break; } - if (_cache2 !== _previousCache2) { - // Run passive effects to retain/release the cache. - workInProgress.flags |= Passive$1; + default: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + break; } } - - popTransition(workInProgress, current); - return null; } - case CacheComponent: { - { - var _previousCache3 = null; - - if (current !== null) { - _previousCache3 = current.memoizedState.cache; - } + function abortRootTransitions( + root, + abort, + deletedTransitions, + deletedOffscreenInstance, + isInDeletedTree + ) { + if (enableTransitionTracing) { + var rootTransitions = root.incompleteTransitions; + deletedTransitions.forEach(function (transition) { + if (rootTransitions.has(transition)) { + var transitionInstance = rootTransitions.get(transition); - var _cache3 = workInProgress.memoizedState.cache; + if (transitionInstance.aborts === null) { + transitionInstance.aborts = []; + } - if (_cache3 !== _previousCache3) { - // Run passive effects to retain/release the cache. - workInProgress.flags |= Passive$1; - } + transitionInstance.aborts.push(abort); - popCacheProvider(workInProgress); - bubbleProperties(workInProgress); + if (deletedOffscreenInstance !== null) { + if ( + transitionInstance.pendingBoundaries !== null && + transitionInstance.pendingBoundaries.has( + deletedOffscreenInstance + ) + ) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + transitionInstance.pendingBoundaries.delete( + deletedOffscreenInstance + ); + } + } + } + }); } + } - return null; + function abortTracingMarkerTransitions( + abortedFiber, + abort, + deletedTransitions, + deletedOffscreenInstance, + isInDeletedTree + ) { + if (enableTransitionTracing) { + var markerInstance = abortedFiber.stateNode; + var markerTransitions = markerInstance.transitions; + var pendingBoundaries = markerInstance.pendingBoundaries; + + if (markerTransitions !== null) { + // TODO: Refactor this code. Is there a way to move this code to + // the deletions phase instead of calculating it here while making sure + // complete is called appropriately? + deletedTransitions.forEach(function (transition) { + // If one of the transitions on the tracing marker is a transition + // that was in an aborted subtree, we will abort that tracing marker + if ( + abortedFiber !== null && + markerTransitions.has(transition) && + (markerInstance.aborts === null || + !markerInstance.aborts.includes(abort)) + ) { + if (markerInstance.transitions !== null) { + if (markerInstance.aborts === null) { + markerInstance.aborts = [abort]; + addMarkerIncompleteCallbackToPendingTransition( + abortedFiber.memoizedProps.name, + markerInstance.transitions, + markerInstance.aborts + ); + } else { + markerInstance.aborts.push(abort); + } // We only want to call onTransitionProgress when the marker hasn't been + // deleted + + if ( + deletedOffscreenInstance !== null && + !isInDeletedTree && + pendingBoundaries !== null && + pendingBoundaries.has(deletedOffscreenInstance) + ) { + pendingBoundaries.delete(deletedOffscreenInstance); + addMarkerProgressCallbackToPendingTransition( + abortedFiber.memoizedProps.name, + deletedTransitions, + pendingBoundaries + ); + } + } + } + }); + } + } } - case TracingMarkerComponent: { + function abortParentMarkerTransitionsForDeletedFiber( + abortedFiber, + abort, + deletedTransitions, + deletedOffscreenInstance, + isInDeletedTree + ) { if (enableTransitionTracing) { - var _instance4 = workInProgress.stateNode; + // Find all pending markers that are waiting on child suspense boundaries in the + // aborted subtree and cancels them + var fiber = abortedFiber; + + while (fiber !== null) { + switch (fiber.tag) { + case TracingMarkerComponent: + abortTracingMarkerTransitions( + fiber, + abort, + deletedTransitions, + deletedOffscreenInstance, + isInDeletedTree + ); + break; - if (_instance4 !== null) { - popMarkerInstance(workInProgress); - } + case HostRoot: + var root = fiber.stateNode; + abortRootTransitions( + root, + abort, + deletedTransitions, + deletedOffscreenInstance + ); + break; + } - bubbleProperties(workInProgress); + fiber = fiber.return; + } } - - return null; } - } - throw new Error( - "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in " + - "React. Please file an issue." - ); -} + function commitTransitionProgress(offscreenFiber) { + if (enableTransitionTracing) { + // This function adds suspense boundaries to the root + // or tracing marker's pendingBoundaries map. + // When a suspense boundary goes from a resolved to a fallback + // state we add the boundary to the map, and when it goes from + // a fallback to a resolved state, we remove the boundary from + // the map. + // We use stateNode on the Offscreen component as a stable object + // that doesnt change from render to render. This way we can + // distinguish between different Offscreen instances (vs. the same + // Offscreen instance with different fibers) + var offscreenInstance = offscreenFiber.stateNode; + var prevState = null; + var previousFiber = offscreenFiber.alternate; + + if (previousFiber !== null && previousFiber.memoizedState !== null) { + prevState = previousFiber.memoizedState; + } + + var nextState = offscreenFiber.memoizedState; + var wasHidden = prevState !== null; + var isHidden = nextState !== null; + var pendingMarkers = offscreenInstance._pendingMarkers; // If there is a name on the suspense boundary, store that in + // the pending boundaries. + + var name = null; + var parent = offscreenFiber.return; -function unwindWork(current, workInProgress, renderLanes) { - switch (workInProgress.tag) { - case ClassComponent: { - var Component = workInProgress.type; + if ( + parent !== null && + parent.tag === SuspenseComponent && + parent.memoizedProps.unstable_name + ) { + name = parent.memoizedProps.unstable_name; + } - if (isContextProvider(Component)) { - popContext(workInProgress); - } + if (!wasHidden && isHidden) { + // The suspense boundaries was just hidden. Add the boundary + // to the pending boundary set if it's there + if (pendingMarkers !== null) { + pendingMarkers.forEach(function (markerInstance) { + var pendingBoundaries = markerInstance.pendingBoundaries; + var transitions = markerInstance.transitions; + var markerName = markerInstance.name; - var flags = workInProgress.flags; + if ( + pendingBoundaries !== null && + !pendingBoundaries.has(offscreenInstance) + ) { + pendingBoundaries.set(offscreenInstance, { + name: name + }); - if (flags & ShouldCapture) { - workInProgress.flags = (flags & ~ShouldCapture) | DidCapture; + if (transitions !== null) { + if ( + markerInstance.tag === TransitionTracingMarker && + markerName !== null + ) { + addMarkerProgressCallbackToPendingTransition( + markerName, + transitions, + pendingBoundaries + ); + } else if (markerInstance.tag === TransitionRoot) { + transitions.forEach(function (transition) { + addTransitionProgressCallbackToPendingTransition( + transition, + pendingBoundaries + ); + }); + } + } + } + }); + } + } else if (wasHidden && !isHidden) { + // The suspense boundary went from hidden to visible. Remove + // the boundary from the pending suspense boundaries set + // if it's there + if (pendingMarkers !== null) { + pendingMarkers.forEach(function (markerInstance) { + var pendingBoundaries = markerInstance.pendingBoundaries; + var transitions = markerInstance.transitions; + var markerName = markerInstance.name; - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); + if ( + pendingBoundaries !== null && + pendingBoundaries.has(offscreenInstance) + ) { + pendingBoundaries.delete(offscreenInstance); + + if (transitions !== null) { + if ( + markerInstance.tag === TransitionTracingMarker && + markerName !== null + ) { + addMarkerProgressCallbackToPendingTransition( + markerName, + transitions, + pendingBoundaries + ); // If there are no more unresolved suspense boundaries, the interaction + // is considered finished + + if (pendingBoundaries.size === 0) { + if (markerInstance.aborts === null) { + addMarkerCompleteCallbackToPendingTransition( + markerName, + transitions + ); + } + + markerInstance.transitions = null; + markerInstance.pendingBoundaries = null; + markerInstance.aborts = null; + } + } else if (markerInstance.tag === TransitionRoot) { + transitions.forEach(function (transition) { + addTransitionProgressCallbackToPendingTransition( + transition, + pendingBoundaries + ); + }); + } + } + } + }); + } } - - return workInProgress; } - - return null; } - case HostRoot: { + function hideOrUnhideAllChildren(finishedWork, isHidden) { + // Only hide or unhide the top-most host nodes. + var hostSubtreeRoot = null; + { - popCacheProvider(workInProgress); - } + // We only have the top Fiber that was inserted but we need to recurse down its + // children to find all the terminal nodes. + var node = finishedWork; - if (enableTransitionTracing) { - popRootMarkerInstance(workInProgress); - } + while (true) { + if (node.tag === HostComponent || false || false) { + if (hostSubtreeRoot === null) { + hostSubtreeRoot = node; - popRootTransition(workInProgress); - popHostContainer(workInProgress); - popTopLevelContextObject(workInProgress); - var _flags = workInProgress.flags; + try { + var instance = node.stateNode; - if ( - (_flags & ShouldCapture) !== NoFlags$1 && - (_flags & DidCapture) === NoFlags$1 - ) { - // There was an error during render that wasn't captured by a suspense - // boundary. Do a second pass on the root to unmount the children. - workInProgress.flags = (_flags & ~ShouldCapture) | DidCapture; - return workInProgress; - } // We unwound to the root without completing it. Exit. + if (isHidden) { + hideInstance(instance); + } else { + unhideInstance(node.stateNode, node.memoizedProps); + } + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } + } + } else if (node.tag === HostText) { + if (hostSubtreeRoot === null) { + try { + var _instance = node.stateNode; - return null; - } + if (isHidden) { + hideTextInstance(_instance); + } else { + unhideTextInstance(_instance, node.memoizedProps); + } + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } + } + } else if ( + (node.tag === OffscreenComponent || + node.tag === LegacyHiddenComponent) && + node.memoizedState !== null && + node !== finishedWork + ); + else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } - case HostHoistable: - case HostSingleton: - case HostComponent: { - // TODO: popHydrationState - popHostContext(workInProgress); - return null; - } + if (node === finishedWork) { + return; + } - case SuspenseComponent: { - popSuspenseHandler(workInProgress); - var suspenseState = workInProgress.memoizedState; + while (node.sibling === null) { + if (node.return === null || node.return === finishedWork) { + return; + } - if (suspenseState !== null && suspenseState.dehydrated !== null) { - if (workInProgress.alternate === null) { - throw new Error( - "Threw in newly mounted dehydrated component. This is likely a bug in " + - "React. Please file an issue." - ); - } - } + if (hostSubtreeRoot === node) { + hostSubtreeRoot = null; + } - var _flags2 = workInProgress.flags; + node = node.return; + } - if (_flags2 & ShouldCapture) { - workInProgress.flags = (_flags2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. + if (hostSubtreeRoot === node) { + hostSubtreeRoot = null; + } - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); + node.sibling.return = node.return; + node = node.sibling; } - - return workInProgress; } - - return null; } - case SuspenseListComponent: { - popSuspenseListContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been - // caught by a nested boundary. If not, it should bubble through. + function commitAttachRef(finishedWork) { + var ref = finishedWork.ref; - return null; - } + if (ref !== null) { + var instance = finishedWork.stateNode; + var instanceToUse; - case HostPortal: - popHostContainer(workInProgress); - return null; + switch (finishedWork.tag) { + case HostHoistable: + case HostSingleton: + case HostComponent: + instanceToUse = getPublicInstance(instance); + break; - case ContextProvider: - var context = workInProgress.type._context; - popProvider(context, workInProgress); - return null; + default: + instanceToUse = instance; + } // Moved outside to ensure DCE works with this flag - case OffscreenComponent: - case LegacyHiddenComponent: { - popSuspenseHandler(workInProgress); - popHiddenContext(workInProgress); - popTransition(workInProgress, current); - var _flags3 = workInProgress.flags; + if (finishedWork.tag === ScopeComponent) { + instanceToUse = instance; + } - if (_flags3 & ShouldCapture) { - workInProgress.flags = (_flags3 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. + if (typeof ref === "function") { + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + finishedWork.refCleanup = ref(instanceToUse); + } finally { + recordLayoutEffectDuration(finishedWork); + } + } else { + finishedWork.refCleanup = ref(instanceToUse); + } + } else { + { + if (!ref.hasOwnProperty("current")) { + error( + "Unexpected ref object provided for %s. " + + "Use either a ref-setter function or React.createRef().", + getComponentNameFromFiber(finishedWork) + ); + } + } // $FlowFixMe[incompatible-use] unable to narrow type to the non-function case - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); + ref.current = instanceToUse; } - - return workInProgress; } - - return null; } - case CacheComponent: - { - popCacheProvider(workInProgress); + function detachFiberMutation(fiber) { + // Cut off the return pointer to disconnect it from the tree. + // This enables us to detect and warn against state updates on an unmounted component. + // It also prevents events from bubbling from within disconnected components. + // + // Ideally, we should also clear the child pointer of the parent alternate to let this + // get GC:ed but we don't know which for sure which parent is the current + // one so we'll settle for GC:ing the subtree of this child. + // This child itself will be GC:ed when the parent updates the next time. + // + // Note that we can't clear child or sibling pointers yet. + // They're needed for passive effects and for findDOMNode. + // We defer those fields, and all other cleanup, to the passive phase (see detachFiberAfterEffects). + // + // Don't reset the alternate yet, either. We need that so we can detach the + // alternate's fields in the passive phase. Clearing the return pointer is + // sufficient for findDOMNode semantics. + var alternate = fiber.alternate; + + if (alternate !== null) { + alternate.return = null; } - return null; + fiber.return = null; + } - case TracingMarkerComponent: - if (enableTransitionTracing) { - if (workInProgress.stateNode !== null) { - popMarkerInstance(workInProgress); - } - } + function detachFiberAfterEffects(fiber) { + var alternate = fiber.alternate; - return null; + if (alternate !== null) { + fiber.alternate = null; + detachFiberAfterEffects(alternate); + } // Clear cyclical Fiber fields. This level alone is designed to roughly + // approximate the planned Fiber refactor. In that world, `setState` will be + // bound to a special "instance" object instead of a Fiber. The Instance + // object will not have any of these fields. It will only be connected to + // the fiber tree via a single link at the root. So if this level alone is + // sufficient to fix memory issues, that bodes well for our plans. - default: - return null; - } -} + fiber.child = null; + fiber.deletions = null; + fiber.sibling = null; // The `stateNode` is cyclical because on host nodes it points to the host -function unwindInterruptedWork(current, interruptedWork, renderLanes) { - switch (interruptedWork.tag) { - case ClassComponent: { - var childContextTypes = interruptedWork.type.childContextTypes; + fiber.stateNode = null; - if (childContextTypes !== null && childContextTypes !== undefined) { - popContext(interruptedWork); - } + { + fiber._debugSource = null; + fiber._debugOwner = null; + } // Theoretically, nothing in here should be necessary, because we already + // disconnected the fiber from the tree. So even if something leaks this + // particular fiber, it won't leak anything else. - break; + fiber.return = null; + fiber.dependencies = null; + fiber.memoizedProps = null; + fiber.memoizedState = null; + fiber.pendingProps = null; + fiber.stateNode = null; // TODO: Move to `commitPassiveUnmountInsideDeletedTreeOnFiber` instead. + + fiber.updateQueue = null; } - case HostRoot: { - { - popCacheProvider(interruptedWork); - } + function getHostParentFiber(fiber) { + var parent = fiber.return; - if (enableTransitionTracing) { - popRootMarkerInstance(interruptedWork); + while (parent !== null) { + if (isHostParent(parent)) { + return parent; + } + + parent = parent.return; } - popRootTransition(interruptedWork); - popHostContainer(interruptedWork); - popTopLevelContextObject(interruptedWork); - break; + throw new Error( + "Expected to find a host parent. This error is likely caused by a bug " + + "in React. Please file an issue." + ); } - case HostHoistable: - case HostSingleton: - case HostComponent: { - popHostContext(interruptedWork); - break; + function isHostParent(fiber) { + return ( + fiber.tag === HostComponent || + fiber.tag === HostRoot || + false || + false || + fiber.tag === HostPortal + ); } - case HostPortal: - popHostContainer(interruptedWork); - break; + function getHostSibling(fiber) { + // We're going to search forward into the tree until we find a sibling host + // node. Unfortunately, if multiple insertions are done in a row we have to + // search past them. This leads to exponential search for the next sibling. + // TODO: Find a more efficient way to do this. + var node = fiber; - case SuspenseComponent: - popSuspenseHandler(interruptedWork); - break; + siblings: while (true) { + // If we didn't find anything, let's try the next sibling. + while (node.sibling === null) { + if (node.return === null || isHostParent(node.return)) { + // If we pop out of the root or hit the parent the fiber we are the + // last sibling. + return null; + } // $FlowFixMe[incompatible-type] found when upgrading Flow - case SuspenseListComponent: - popSuspenseListContext(interruptedWork); - break; + node = node.return; + } - case ContextProvider: - var context = interruptedWork.type._context; - popProvider(context, interruptedWork); - break; + node.sibling.return = node.return; + node = node.sibling; - case OffscreenComponent: - case LegacyHiddenComponent: - popSuspenseHandler(interruptedWork); - popHiddenContext(interruptedWork); - popTransition(interruptedWork, current); - break; + while ( + node.tag !== HostComponent && + node.tag !== HostText && + true && + node.tag !== DehydratedFragment + ) { + // If it is not host node and, we might have a host node inside it. + // Try to search down until we find one. + if (node.flags & Placement) { + // If we don't have a child, try the siblings instead. + continue siblings; + } // If we don't have a child, try the siblings instead. + // We also skip portals because they are not part of this host tree. + + if (node.child === null || node.tag === HostPortal) { + continue siblings; + } else { + node.child.return = node; + node = node.child; + } + } // Check if this host node is stable or about to be placed. - case CacheComponent: - { - popCacheProvider(interruptedWork); + if (!(node.flags & Placement)) { + // Found it! + return node.stateNode; + } } + } - break; + function commitPlacement(finishedWork) { + var parentFiber = getHostParentFiber(finishedWork); - case TracingMarkerComponent: - if (enableTransitionTracing) { - var instance = interruptedWork.stateNode; + switch (parentFiber.tag) { + case HostSingleton: - if (instance !== null) { - popMarkerInstance(interruptedWork); - } - } + case HostComponent: { + var _parent = parentFiber.stateNode; - break; - } -} + if (parentFiber.flags & ContentReset) { + parentFiber.flags &= ~ContentReset; + } -// Provided by www -var ReactFbErrorUtils = require("ReactFbErrorUtils"); + var _before = getHostSibling(finishedWork); // We only have the top Fiber that was inserted but we need to recurse down its + // children to find all the terminal nodes. -if (typeof ReactFbErrorUtils.invokeGuardedCallback !== "function") { - throw new Error( - "Expected ReactFbErrorUtils.invokeGuardedCallback to be a function." - ); -} + insertOrAppendPlacementNode(finishedWork, _before, _parent); + break; + } -function invokeGuardedCallbackImpl(name, func, context, a, b, c, d, e, f) { - // This will call `this.onError(err)` if an error was caught. - ReactFbErrorUtils.invokeGuardedCallback.apply(this, arguments); -} + case HostRoot: + case HostPortal: { + var _parent2 = parentFiber.stateNode.containerInfo; -var hasError = false; -var caughtError = null; // Used by event system to capture/rethrow the first error. -var reporter = { - onError: function (error) { - hasError = true; - caughtError = error; - } -}; -/** - * Call a function while guarding against errors that happens within it. - * Returns an error if it throws, otherwise null. - * - * In production, this is implemented using a try-catch. The reason we don't - * use a try-catch directly is so that we can swap out a different - * implementation in DEV mode. - * - * @param {String} name of the guard to use for logging or debugging - * @param {Function} func The function to invoke - * @param {*} context The context to use when calling the function - * @param {...*} args Arguments for function - */ + var _before2 = getHostSibling(finishedWork); -function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) { - hasError = false; - caughtError = null; - invokeGuardedCallbackImpl.apply(reporter, arguments); -} -function hasCaughtError() { - return hasError; -} -function clearCaughtError() { - if (hasError) { - var error = caughtError; - hasError = false; - caughtError = null; - return error; - } else { - 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." - ); - } -} + insertOrAppendPlacementNodeIntoContainer( + finishedWork, + _before2, + _parent2 + ); + break; + } -var didWarnAboutUndefinedSnapshotBeforeUpdate = null; + default: + throw new Error( + "Invalid host parent fiber. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + } + } -{ - didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); -} // Used during the commit phase to track the state of the Offscreen component stack. -// Allows us to avoid traversing the return path to find the nearest Offscreen ancestor. + function insertOrAppendPlacementNodeIntoContainer(node, before, parent) { + var tag = node.tag; + var isHost = tag === HostComponent || tag === HostText; -var offscreenSubtreeIsHidden = false; -var offscreenSubtreeWasHidden = false; -var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; -var nextEffect = null; // Used for Profiling builds to track updaters. + if (isHost) { + var stateNode = node.stateNode; -var inProgressLanes = null; -var inProgressRoot = null; + if (before) { + insertInContainerBefore(parent, stateNode, before); + } else { + appendChildToContainer(parent, stateNode); + } + } else if (tag === HostPortal || false); + else { + var child = node.child; -function shouldProfile(current) { - return ( - (current.mode & ProfileMode) !== NoMode && - (getExecutionContext() & CommitContext) !== NoContext - ); -} + if (child !== null) { + insertOrAppendPlacementNodeIntoContainer(child, before, parent); + var sibling = child.sibling; -function reportUncaughtErrorInDEV(error) { - // Wrapping each small part of the commit phase into a guarded - // callback is a bit too slow (https://github.com/facebook/react/pull/21666). - // But we rely on it to surface errors to DEV tools like overlays - // (https://github.com/facebook/react/issues/21712). - // As a compromise, rethrow only caught errors in a guard. - { - invokeGuardedCallback(null, function () { - throw error; - }); - clearCaughtError(); - } -} + while (sibling !== null) { + insertOrAppendPlacementNodeIntoContainer(sibling, before, parent); + sibling = sibling.sibling; + } + } + } + } -function callComponentWillUnmountWithTimer(current, instance) { - instance.props = current.memoizedProps; - instance.state = current.memoizedState; - - if (shouldProfile(current)) { - try { - startLayoutEffectTimer(); - instance.componentWillUnmount(); - } finally { - recordLayoutEffectDuration(current); - } - } else { - instance.componentWillUnmount(); - } -} // Capture errors so they don't interrupt unmounting. - -function safelyCallComponentWillUnmount( - current, - nearestMountedAncestor, - instance -) { - try { - callComponentWillUnmountWithTimer(current, instance); - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } -} // Capture errors so they don't interrupt mounting. - -function safelyAttachRef(current, nearestMountedAncestor) { - try { - commitAttachRef(current); - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } -} + function insertOrAppendPlacementNode(node, before, parent) { + var tag = node.tag; + var isHost = tag === HostComponent || tag === HostText; -function safelyDetachRef(current, nearestMountedAncestor) { - var ref = current.ref; - var refCleanup = current.refCleanup; + if (isHost) { + var stateNode = node.stateNode; - if (ref !== null) { - if (typeof refCleanup === "function") { - try { - if (shouldProfile(current)) { - try { - startLayoutEffectTimer(); - refCleanup(); - } finally { - recordLayoutEffectDuration(current); - } + if (before) { + insertBefore(parent, stateNode, before); } else { - refCleanup(); + appendChild(parent, stateNode); } - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } finally { - // `refCleanup` has been called. Nullify all references to it to prevent double invocation. - current.refCleanup = null; - var finishedWork = current.alternate; + } else if (tag === HostPortal || false); + else { + var child = node.child; - if (finishedWork != null) { - finishedWork.refCleanup = null; - } - } - } else if (typeof ref === "function") { - var retVal; + if (child !== null) { + insertOrAppendPlacementNode(child, before, parent); + var sibling = child.sibling; - try { - if (shouldProfile(current)) { - try { - startLayoutEffectTimer(); - retVal = ref(null); - } finally { - recordLayoutEffectDuration(current); + while (sibling !== null) { + insertOrAppendPlacementNode(sibling, before, parent); + sibling = sibling.sibling; } - } else { - retVal = ref(null); } - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); } + } // These are tracked on the stack as we recursively traverse a + // deleted subtree. + // TODO: Update these during the whole mutation phase, not just during + // a deletion. - { - if (typeof retVal === "function") { - error( - "Unexpected return value from a callback ref in %s. " + - "A callback ref should not return a function.", - getComponentNameFromFiber(current) - ); - } - } - } else { - // $FlowFixMe[incompatible-use] unable to narrow type to RefObject - ref.current = null; - } - } -} + var hostParent = null; + var hostParentIsContainer = false; -function safelyCallDestroy(current, nearestMountedAncestor, destroy) { - try { - destroy(); - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } -} + function commitDeletionEffects(root, returnFiber, deletedFiber) { + { + // We only have the top Fiber that was deleted but we need to recurse down its + // children to find all the terminal nodes. + // Recursively delete all host nodes from the parent, detach refs, clean + // up mounted layout effects, and call componentWillUnmount. + // We only need to remove the topmost host child in each branch. But then we + // still need to keep traversing to unmount effects, refs, and cWU. TODO: We + // could split this into two separate traversals functions, where the second + // one doesn't include any removeChild logic. This is maybe the same + // function as "disappearLayoutEffects" (or whatever that turns into after + // the layout phase is refactored to use recursion). + // Before starting, find the nearest host parent on the stack so we know + // which instance/container to remove the children from. + // TODO: Instead of searching up the fiber return path on every deletion, we + // can track the nearest host component on the JS stack as we traverse the + // tree during the commit phase. This would make insertions faster, too. + var parent = returnFiber; + + findParent: while (parent !== null) { + switch (parent.tag) { + case HostSingleton: + case HostComponent: { + hostParent = parent.stateNode; + hostParentIsContainer = false; + break findParent; + } -var focusedInstanceHandle = null; -var shouldFireAfterActiveInstanceBlur = false; -function commitBeforeMutationEffects(root, firstChild) { - focusedInstanceHandle = prepareForCommit(); - nextEffect = firstChild; - commitBeforeMutationEffects_begin(); // We no longer need to track the active instance fiber - - var shouldFire = shouldFireAfterActiveInstanceBlur; - shouldFireAfterActiveInstanceBlur = false; - focusedInstanceHandle = null; - return shouldFire; -} + case HostRoot: { + hostParent = parent.stateNode.containerInfo; + hostParentIsContainer = true; + break findParent; + } -function commitBeforeMutationEffects_begin() { - while (nextEffect !== null) { - var fiber = nextEffect; // This phase is only used for beforeActiveInstanceBlur. - // Let's skip the whole loop if it's off. + case HostPortal: { + hostParent = parent.stateNode.containerInfo; + hostParentIsContainer = true; + break findParent; + } + } - { - // TODO: Should wrap this in flags check, too, as optimization - var deletions = fiber.deletions; + parent = parent.return; + } - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var deletion = deletions[i]; - commitBeforeMutationEffectsDeletion(deletion); + if (hostParent === null) { + throw new Error( + "Expected to find a host parent. This error is likely caused by " + + "a bug in React. Please file an issue." + ); } - } - } - var child = fiber.child; + commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber); + hostParent = null; + hostParentIsContainer = false; + } - if ( - (fiber.subtreeFlags & BeforeMutationMask) !== NoFlags$1 && - child !== null - ) { - child.return = fiber; - nextEffect = child; - } else { - commitBeforeMutationEffects_complete(); + detachFiberMutation(deletedFiber); } - } -} -function commitBeforeMutationEffects_complete() { - while (nextEffect !== null) { - var fiber = nextEffect; - setCurrentFiber(fiber); + function recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + parent + ) { + // TODO: Use a static flag to skip trees that don't have unmount effects + var child = parent.child; - try { - commitBeforeMutationEffectsOnFiber(fiber); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); + while (child !== null) { + commitDeletionEffectsOnFiber( + finishedRoot, + nearestMountedAncestor, + child + ); + child = child.sibling; + } } - resetCurrentFiber(); - var sibling = fiber.sibling; - - if (sibling !== null) { - sibling.return = fiber.return; - nextEffect = sibling; - return; - } + function commitDeletionEffectsOnFiber( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ) { + onCommitUnmount(deletedFiber); // The cases in this outer switch modify the stack before they traverse + // into their subtree. There are simpler cases in the inner switch + // that don't modify the stack. - nextEffect = fiber.return; - } -} + switch (deletedFiber.tag) { + case HostHoistable: -function commitBeforeMutationEffectsOnFiber(finishedWork) { - var current = finishedWork.alternate; - var flags = finishedWork.flags; + case HostSingleton: - { - if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) { - // Check to see if the focused element was inside of a hidden (Suspense) subtree. - // TODO: Move this out of the hot path using a dedicated effect tag. - if ( - finishedWork.tag === SuspenseComponent && - isSuspenseBoundaryBeingHidden(current, finishedWork) && // $FlowFixMe[incompatible-call] found when upgrading Flow - doesFiberContain(finishedWork, focusedInstanceHandle) - ) { - shouldFireAfterActiveInstanceBlur = true; - } - } - } + case HostComponent: { + if (!offscreenSubtreeWasHidden) { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + } // Intentional fallthrough to next branch + } - if ((flags & Snapshot) !== NoFlags$1) { - setCurrentFiber(finishedWork); - } + case HostText: { + // We only need to remove the nearest host child. Set the host parent + // to `null` on the stack to indicate that nested children don't + // need to be removed. + { + var _prevHostParent = hostParent; + var _prevHostParentIsContainer = hostParentIsContainer; + hostParent = null; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + hostParent = _prevHostParent; + hostParentIsContainer = _prevHostParentIsContainer; + + if (hostParent !== null) { + // Now that all the child effects have unmounted, we can remove the + // node from the tree. + if (hostParentIsContainer) { + removeChildFromContainer(hostParent, deletedFiber.stateNode); + } else { + removeChild(hostParent, deletedFiber.stateNode); + } + } + } - switch (finishedWork.tag) { - case FunctionComponent: { - { - if ((flags & Update) !== NoFlags$1) { - commitUseEffectEventMount(finishedWork); + return; } - } - break; - } + case DehydratedFragment: { + { + var hydrationCallbacks = finishedRoot.hydrationCallbacks; - case ForwardRef: - case SimpleMemoComponent: { - break; - } + if (hydrationCallbacks !== null) { + var onDeleted = hydrationCallbacks.onDeleted; - case ClassComponent: { - if ((flags & Snapshot) !== NoFlags$1) { - if (current !== null) { - var prevProps = current.memoizedProps; - var prevState = current.memoizedState; - var instance = finishedWork.stateNode; // We could update instance props and state here, - // but instead we rely on them being set during last render. - // TODO: revisit this when we implement resuming. + if (onDeleted) { + onDeleted(deletedFiber.stateNode); + } + } + } // Dehydrated fragments don't have any children + // Delete the dehydrated suspense boundary and all of its content. { - if ( - finishedWork.type === finishedWork.elementType && - !didWarnAboutReassigningProps - ) { - if (instance.props !== finishedWork.memoizedProps) { - 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" - ); + if (hostParent !== null) { + if (hostParentIsContainer) { + clearSuspenseBoundaryFromContainer(); + } else { + clearSuspenseBoundary(); } + } + } - if (instance.state !== finishedWork.memoizedState) { - 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" - ); + return; + } + + case HostPortal: { + { + // When we go into a portal, it becomes the parent to remove from. + var _prevHostParent2 = hostParent; + var _prevHostParentIsContainer2 = hostParentIsContainer; + hostParent = deletedFiber.stateNode.containerInfo; + hostParentIsContainer = true; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + hostParent = _prevHostParent2; + hostParentIsContainer = _prevHostParentIsContainer2; + } + + return; + } + + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + if (!offscreenSubtreeWasHidden) { + var updateQueue = deletedFiber.updateQueue; + + if (updateQueue !== null) { + var lastEffect = updateQueue.lastEffect; + + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; + + do { + var tag = effect.tag; + var inst = effect.inst; + var destroy = inst.destroy; + + if (destroy !== undefined) { + if ((tag & Insertion) !== NoFlags) { + inst.destroy = undefined; + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + } else if ((tag & Layout) !== NoFlags) { + if (enableSchedulingProfiler) { + markComponentLayoutEffectUnmountStarted(deletedFiber); + } + + if (shouldProfile(deletedFiber)) { + startLayoutEffectTimer(); + inst.destroy = undefined; + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + recordLayoutEffectDuration(deletedFiber); + } else { + inst.destroy = undefined; + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + } + + if (enableSchedulingProfiler) { + markComponentLayoutEffectUnmountStopped(); + } + } + } + + effect = effect.next; + } while (effect !== firstEffect); } } } - var snapshot = instance.getSnapshotBeforeUpdate( - finishedWork.elementType === finishedWork.type - ? prevProps - : resolveDefaultProps(finishedWork.type, prevProps), - prevState + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber ); + return; + } - { - var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate; - - if (snapshot === undefined && !didWarnSet.has(finishedWork.type)) { - didWarnSet.add(finishedWork.type); + case ClassComponent: { + if (!offscreenSubtreeWasHidden) { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + var instance = deletedFiber.stateNode; - error( - "%s.getSnapshotBeforeUpdate(): A snapshot value (or null) " + - "must be returned. You have returned undefined.", - getComponentNameFromFiber(finishedWork) + if (typeof instance.componentWillUnmount === "function") { + safelyCallComponentWillUnmount( + deletedFiber, + nearestMountedAncestor, + instance ); } } - instance.__reactInternalSnapshotBeforeUpdate = snapshot; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; + } + + case ScopeComponent: { + { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + } + + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; + } + + case OffscreenComponent: { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + + if (deletedFiber.mode & ConcurrentMode) { + // If this offscreen component is hidden, we already unmounted it. Before + // deleting the children, track that it's already unmounted so that we + // don't attempt to unmount the effects again. + // TODO: If the tree is hidden, in most cases we should be able to skip + // over the nested children entirely. An exception is we haven't yet found + // the topmost host node to delete, which we already track on the stack. + // But the other case is portals, which need to be detached no matter how + // deeply they are nested. We should use a subtree flag to track whether a + // subtree includes a nested portal. + var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; + offscreenSubtreeWasHidden = + prevOffscreenSubtreeWasHidden || + deletedFiber.memoizedState !== null; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; + } else { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + } + + break; + } + + default: { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; } } + } + + function commitSuspenseCallback(finishedWork) { + // TODO: Move this to passive phase + var newState = finishedWork.memoizedState; - break; + if (newState !== null) { + var suspenseCallback = finishedWork.memoizedProps.suspenseCallback; + + if (typeof suspenseCallback === "function") { + var retryQueue = finishedWork.updateQueue; + + if (retryQueue !== null) { + suspenseCallback(new Set(retryQueue)); + } + } else { + if (suspenseCallback !== undefined) { + error("Unexpected type for suspenseCallback."); + } + } + } } - case HostRoot: { - break; + function getRetryCache(finishedWork) { + // TODO: Unify the interface for the retry cache so we don't have to switch + // on the tag like this. + switch (finishedWork.tag) { + case SuspenseComponent: + case SuspenseListComponent: { + var retryCache = finishedWork.stateNode; + + if (retryCache === null) { + retryCache = finishedWork.stateNode = new PossiblyWeakSet(); + } + + return retryCache; + } + + case OffscreenComponent: { + var instance = finishedWork.stateNode; + var _retryCache = instance._retryCache; + + if (_retryCache === null) { + _retryCache = instance._retryCache = new PossiblyWeakSet(); + } + + return _retryCache; + } + + default: { + throw new Error( + "Unexpected Suspense handler tag (" + + finishedWork.tag + + "). This is a " + + "bug in React." + ); + } + } } - case HostComponent: - case HostHoistable: - case HostSingleton: - case HostText: - case HostPortal: - case IncompleteClassComponent: - // Nothing to do for these component types - break; + function detachOffscreenInstance(instance) { + var fiber = instance._current; - default: { - if ((flags & Snapshot) !== NoFlags$1) { + if (fiber === null) { 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." + "Calling Offscreen.detach before instance handle has been set." ); } - } - } - if ((flags & Snapshot) !== NoFlags$1) { - resetCurrentFiber(); - } -} + if ((instance._pendingVisibility & OffscreenDetached) !== NoFlags$1) { + // The instance is already detached, this is a noop. + return; + } // TODO: There is an opportunity to optimise this by not entering commit phase + // and unmounting effects directly. + + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); -function commitBeforeMutationEffectsDeletion(deletion) { - { - // TODO (effects) It would be nice to avoid calling doesFiberContain() - // Maybe we can repurpose one of the subtreeFlags positions for this instead? - // Use it to store which part of the tree the focused instance is in? - // This assumes we can safely determine that instance during the "render" phase. - if (doesFiberContain(deletion, focusedInstanceHandle)) { - shouldFireAfterActiveInstanceBlur = true; + if (root !== null) { + instance._pendingVisibility |= OffscreenDetached; + scheduleUpdateOnFiber(root, fiber, SyncLane); + } } - } -} + function attachOffscreenInstance(instance) { + var fiber = instance._current; + + if (fiber === null) { + throw new Error( + "Calling Offscreen.detach before instance handle has been set." + ); + } -function commitHookEffectListUnmount( - flags, - finishedWork, - nearestMountedAncestor -) { - var updateQueue = finishedWork.updateQueue; - var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; + if ((instance._pendingVisibility & OffscreenDetached) === NoFlags$1) { + // The instance is already attached, this is a noop. + return; + } - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - do { - if ((effect.tag & flags) === flags) { - // Unmount - var inst = effect.inst; - var destroy = inst.destroy; + if (root !== null) { + instance._pendingVisibility &= ~OffscreenDetached; + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + } - if (destroy !== undefined) { - inst.destroy = undefined; + function attachSuspenseRetryListeners(finishedWork, wakeables) { + // If this boundary just timed out, then it will have a set of wakeables. + // For each wakeable, attach a listener so that when it resolves, React + // attempts to re-render the boundary in the primary (pre-timeout) state. + var retryCache = getRetryCache(finishedWork); + wakeables.forEach(function (wakeable) { + // Memoize using the boundary fiber to prevent redundant listeners. + var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); - if (enableSchedulingProfiler) { - if ((flags & Passive) !== NoFlags) { - markComponentPassiveEffectUnmountStarted(finishedWork); - } else if ((flags & Layout) !== NoFlags) { - markComponentLayoutEffectUnmountStarted(finishedWork); - } - } + if (!retryCache.has(wakeable)) { + retryCache.add(wakeable); { - if ((flags & Insertion) !== NoFlags) { - setIsRunningInsertionEffect(true); + if (isDevToolsPresent) { + if (inProgressLanes !== null && inProgressRoot !== null) { + // If we have pending work still, associate the original updaters with it. + restorePendingUpdaters(inProgressRoot, inProgressLanes); + } else { + throw Error( + "Expected finished root and lanes to be set. This is a bug in React." + ); + } } } - safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy); + wakeable.then(retry, retry); + } + }); + } // This function detects when a Suspense boundary goes from visible to hidden. + // It returns false if the boundary is already hidden. + // TODO: Use an effect tag. - { - if ((flags & Insertion) !== NoFlags) { - setIsRunningInsertionEffect(false); - } - } + function isSuspenseBoundaryBeingHidden(current, finishedWork) { + if (current !== null) { + var oldState = current.memoizedState; - if (enableSchedulingProfiler) { - if ((flags & Passive) !== NoFlags) { - markComponentPassiveEffectUnmountStopped(); - } else if ((flags & Layout) !== NoFlags) { - markComponentLayoutEffectUnmountStopped(); - } - } + if (oldState === null || oldState.dehydrated !== null) { + var newState = finishedWork.memoizedState; + return newState !== null && newState.dehydrated === null; } } - effect = effect.next; - } while (effect !== firstEffect); - } -} - -function commitHookEffectListMount(flags, finishedWork) { - var updateQueue = finishedWork.updateQueue; - var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; - - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; + return false; + } + function commitMutationEffects(root, finishedWork, committedLanes) { + inProgressLanes = committedLanes; + inProgressRoot = root; + setCurrentFiber(finishedWork); + commitMutationEffectsOnFiber(finishedWork, root); + setCurrentFiber(finishedWork); + inProgressLanes = null; + inProgressRoot = null; + } - do { - if ((effect.tag & flags) === flags) { - if (enableSchedulingProfiler) { - if ((flags & Passive) !== NoFlags) { - markComponentPassiveEffectMountStarted(finishedWork); - } else if ((flags & Layout) !== NoFlags) { - markComponentLayoutEffectMountStarted(finishedWork); - } - } // Mount + function recursivelyTraverseMutationEffects(root, parentFiber, lanes) { + // Deletions effects can be scheduled on any fiber type. They need to happen + // before the children effects hae fired. + var deletions = parentFiber.deletions; - var create = effect.create; + if (deletions !== null) { + for (var i = 0; i < deletions.length; i++) { + var childToDelete = deletions[i]; - { - if ((flags & Insertion) !== NoFlags) { - setIsRunningInsertionEffect(true); + try { + commitDeletionEffects(root, parentFiber, childToDelete); + } catch (error) { + captureCommitPhaseError(childToDelete, parentFiber, error); } } + } - var inst = effect.inst; - var destroy = create(); - inst.destroy = destroy; + var prevDebugFiber = getCurrentFiber(); - { - if ((flags & Insertion) !== NoFlags) { - setIsRunningInsertionEffect(false); - } - } + if (parentFiber.subtreeFlags & MutationMask) { + var child = parentFiber.child; - if (enableSchedulingProfiler) { - if ((flags & Passive) !== NoFlags) { - markComponentPassiveEffectMountStopped(); - } else if ((flags & Layout) !== NoFlags) { - markComponentLayoutEffectMountStopped(); - } + while (child !== null) { + setCurrentFiber(child); + commitMutationEffectsOnFiber(child, root); + child = child.sibling; } + } - { - if (destroy !== undefined && typeof destroy !== "function") { - var hookName = void 0; + setCurrentFiber(prevDebugFiber); + } - if ((effect.tag & Layout) !== NoFlags$1) { - hookName = "useLayoutEffect"; - } else if ((effect.tag & Insertion) !== NoFlags$1) { - hookName = "useInsertionEffect"; - } else { - hookName = "useEffect"; - } + function commitMutationEffectsOnFiber(finishedWork, root, lanes) { + var current = finishedWork.alternate; + var flags = finishedWork.flags; // The effect flag should be checked *after* we refine the type of fiber, + // because the fiber tag is more specific. An exception is any flag related + // to reconciliation, because those can be set on all fiber types. + + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - var addendum = void 0; + if (flags & Update) { + try { + commitHookEffectListUnmount( + Insertion | HasEffect, + finishedWork, + finishedWork.return + ); + commitHookEffectListMount(Insertion | HasEffect, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } // Layout effects are destroyed during the mutation phase so that all + // destroy functions for all fibers are called before any create functions. + // This prevents sibling component effects from interfering with each other, + // e.g. a destroy function in one component should never override a ref set + // by a create function in another component during the same commit. + + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + commitHookEffectListUnmount( + Layout | HasEffect, + finishedWork, + finishedWork.return + ); + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } - if (destroy === null) { - addendum = - " You returned null. If your effect does not require clean " + - "up, return undefined (or nothing)."; - } else if (typeof destroy.then === "function") { - 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"; + recordLayoutEffectDuration(finishedWork); } else { - addendum = " You returned: " + destroy; + try { + commitHookEffectListUnmount( + Layout | HasEffect, + finishedWork, + finishedWork.return + ); + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } } - - error( - "%s must not return anything besides a function, " + - "which is used for clean-up.%s", - hookName, - addendum - ); } - } - } - - effect = effect.next; - } while (effect !== firstEffect); - } -} - -function commitUseEffectEventMount(finishedWork) { - var updateQueue = finishedWork.updateQueue; - var eventPayloads = updateQueue !== null ? updateQueue.events : null; - - if (eventPayloads !== null) { - for (var ii = 0; ii < eventPayloads.length; ii++) { - var _eventPayloads$ii = eventPayloads[ii], - ref = _eventPayloads$ii.ref, - nextImpl = _eventPayloads$ii.nextImpl; - ref.impl = nextImpl; - } - } -} -function commitPassiveEffectDurations(finishedRoot, finishedWork) { - if (getExecutionContext() & CommitContext) { - // Only Profilers with work in their subtree will have an Update effect scheduled. - if ((finishedWork.flags & Update) !== NoFlags$1) { - switch (finishedWork.tag) { - case Profiler: { - var passiveEffectDuration = - finishedWork.stateNode.passiveEffectDuration; - var _finishedWork$memoize = finishedWork.memoizedProps, - id = _finishedWork$memoize.id, - onPostCommit = _finishedWork$memoize.onPostCommit; // This value will still reflect the previous commit phase. - // It does not get reset until the start of the next commit phase. + return; + } - var commitTime = getCommitTime(); - var phase = finishedWork.alternate === null ? "mount" : "update"; + case ClassComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - { - if (isCurrentUpdateNested()) { - phase = "nested-update"; + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(current, current.return); } } - if (typeof onPostCommit === "function") { - onPostCommit(id, phase, passiveEffectDuration, commitTime); - } // Bubble times to the next nearest ancestor Profiler. - // After we process that Profiler, we'll bubble further up. - - var parentFiber = finishedWork.return; + if (flags & Callback && offscreenSubtreeIsHidden) { + var updateQueue = finishedWork.updateQueue; - outer: while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; - root.passiveEffectDuration += passiveEffectDuration; - break outer; - - case Profiler: - var parentStateNode = parentFiber.stateNode; - parentStateNode.passiveEffectDuration += passiveEffectDuration; - break outer; + if (updateQueue !== null) { + deferHiddenCallbacks(updateQueue); } - - parentFiber = parentFiber.return; } - break; + return; } - } - } - } -} -function commitHookLayoutEffects(finishedWork, hookFlags) { - // At this point layout effects have already been destroyed (during mutation phase). - // This is done to prevent sibling component effects from interfering with each other, - // e.g. a destroy function in one component should never override a ref set - // by a create function in another component during the same commit. - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - commitHookEffectListMount(hookFlags, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - - recordLayoutEffectDuration(finishedWork); - } else { - try { - commitHookEffectListMount(hookFlags, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - } -} + case HostHoistable: -function commitClassLayoutLifecycles(finishedWork, current) { - var instance = finishedWork.stateNode; + case HostSingleton: - if (current === null) { - // We could update instance props and state here, - // but instead we rely on them being set during last render. - // TODO: revisit this when we implement resuming. - { - if ( - finishedWork.type === finishedWork.elementType && - !didWarnAboutReassigningProps - ) { - if (instance.props !== finishedWork.memoizedProps) { - 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" - ); - } + case HostComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - if (instance.state !== finishedWork.memoizedState) { - 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" - ); - } - } - } + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(current, current.return); + } + } - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - instance.componentDidMount(); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + { + // TODO: ContentReset gets cleared by the children during the commit + // phase. This is a refactor hazard because it means we must read + // flags the flags after `commitReconciliationEffects` has already run; + // the order matters. We should refactor so that ContentReset does not + // rely on mutating the flag during commit. Like by setting a flag + // during the render phase instead. + if (finishedWork.flags & ContentReset) { + var instance = finishedWork.stateNode; + + try { + resetTextContent(instance); + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } + } - recordLayoutEffectDuration(finishedWork); - } else { - try { - instance.componentDidMount(); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - } - } else { - var prevProps = - finishedWork.elementType === finishedWork.type - ? current.memoizedProps - : resolveDefaultProps(finishedWork.type, current.memoizedProps); - var prevState = current.memoizedState; // We could update instance props and state here, - // but instead we rely on them being set during last render. - // TODO: revisit this when we implement resuming. + if (flags & Update) { + var _instance2 = finishedWork.stateNode; + + if (_instance2 != null) { + // Commit the work prepared earlier. + var newProps = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps + // as the newProps. The updatePayload will contain the real change in + // this case. + + var oldProps = + current !== null ? current.memoizedProps : newProps; + var type = finishedWork.type; // TODO: Type the updateQueue to be specific to host components. + + var _updatePayload = finishedWork.updateQueue; + finishedWork.updateQueue = null; + + try { + commitUpdate( + _instance2, + _updatePayload, + type, + oldProps, + newProps, + finishedWork + ); + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } + } + } + } - { - if ( - finishedWork.type === finishedWork.elementType && - !didWarnAboutReassigningProps - ) { - if (instance.props !== finishedWork.memoizedProps) { - 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" - ); + return; } - if (instance.state !== finishedWork.memoizedState) { - 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" - ); - } - } - } + case HostText: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - instance.componentDidUpdate( - prevProps, - prevState, - instance.__reactInternalSnapshotBeforeUpdate - ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + if (flags & Update) { + { + if (finishedWork.stateNode === null) { + throw new Error( + "This should have a text node initialized. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + } - recordLayoutEffectDuration(finishedWork); - } else { - try { - instance.componentDidUpdate( - prevProps, - prevState, - instance.__reactInternalSnapshotBeforeUpdate - ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - } - } -} + var textInstance = finishedWork.stateNode; + var newText = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps + // as the newProps. The updatePayload will contain the real change in + // this case. -function commitClassCallbacks(finishedWork) { - // TODO: I think this is now always non-null by the time it reaches the - // commit phase. Consider removing the type check. - var updateQueue = finishedWork.updateQueue; + var oldText = current !== null ? current.memoizedProps : newText; - if (updateQueue !== null) { - var instance = finishedWork.stateNode; + try { + commitTextUpdate(textInstance, oldText, newText); + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } + } + } - { - if ( - finishedWork.type === finishedWork.elementType && - !didWarnAboutReassigningProps - ) { - if (instance.props !== finishedWork.memoizedProps) { - 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" - ); + return; } - if (instance.state !== finishedWork.memoizedState) { - 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" - ); + case HostRoot: { + { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + } + + return; } - } - } // We could update instance props and state here, - // but instead we rely on them being set during last render. - // TODO: revisit this when we implement resuming. - try { - commitCallbacks(updateQueue, instance); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - } -} + case HostPortal: { + { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + } -function commitHostComponentMount(finishedWork) { - var type = finishedWork.type; - var props = finishedWork.memoizedProps; - var instance = finishedWork.stateNode; + return; + } - try { - commitMount(instance, type, props, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } -} + case SuspenseComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); // TODO: We should mark a flag on the Suspense fiber itself, rather than + // relying on the Offscreen fiber having a flag also being marked. The + // reason is that this offscreen fiber might not be part of the work-in- + // progress tree! It could have been reused from a previous render. This + // doesn't lead to incorrect behavior because we don't rely on the flag + // check alone; we also compare the states explicitly below. But for + // modeling purposes, we _should_ be able to rely on the flag check alone. + // So this is a bit fragile. + // + // Also, all this logic could/should move to the passive phase so it + // doesn't block paint. -function commitProfilerUpdate(finishedWork, current) { - if (getExecutionContext() & CommitContext) { - try { - var _finishedWork$memoize2 = finishedWork.memoizedProps, - onCommit = _finishedWork$memoize2.onCommit, - onRender = _finishedWork$memoize2.onRender; - var effectDuration = finishedWork.stateNode.effectDuration; - var commitTime = getCommitTime(); - var phase = current === null ? "mount" : "update"; - - if (enableProfilerNestedUpdatePhase) { - if (isCurrentUpdateNested()) { - phase = "nested-update"; - } - } - - if (typeof onRender === "function") { - onRender( - finishedWork.memoizedProps.id, - phase, - finishedWork.actualDuration, - finishedWork.treeBaseDuration, - finishedWork.actualStartTime, - commitTime - ); - } + var offscreenFiber = finishedWork.child; - if (enableProfilerCommitHooks) { - if (typeof onCommit === "function") { - onCommit( - finishedWork.memoizedProps.id, - phase, - effectDuration, - commitTime - ); - } // Schedule a passive effect for this Profiler to call onPostCommit hooks. - // This effect should be scheduled even if there is no onPostCommit callback for this Profiler, - // because the effect is also where times bubble to parent Profilers. + if (offscreenFiber.flags & Visibility) { + // Throttle the appearance and disappearance of Suspense fallbacks. + var isShowingFallback = finishedWork.memoizedState !== null; + var wasShowingFallback = + current !== null && current.memoizedState !== null; - enqueuePendingPassiveProfilerEffect(finishedWork); // Propagate layout effect durations to the next nearest Profiler ancestor. - // Do not reset these values until the next render so DevTools has a chance to read them first. + if (alwaysThrottleRetries) { + if (isShowingFallback !== wasShowingFallback) { + // A fallback is either appearing or disappearing. + markCommitTimeOfFallback(); + } + } else { + if (isShowingFallback && !wasShowingFallback) { + // Old behavior. Only mark when a fallback appears, not when + // it disappears. + markCommitTimeOfFallback(); + } + } + } - var parentFiber = finishedWork.return; + if (flags & Update) { + try { + commitSuspenseCallback(finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } - outer: while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; - root.effectDuration += effectDuration; - break outer; + var retryQueue = finishedWork.updateQueue; - case Profiler: - var parentStateNode = parentFiber.stateNode; - parentStateNode.effectDuration += effectDuration; - break outer; + if (retryQueue !== null) { + finishedWork.updateQueue = null; + attachSuspenseRetryListeners(finishedWork, retryQueue); + } } - parentFiber = parentFiber.return; + return; } - } - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - } -} -function commitLayoutEffectOnFiber( - finishedRoot, - current, - finishedWork, - committedLanes -) { - // When updating this function, also update reappearLayoutEffects, which does - // most of the same things when an offscreen tree goes from hidden -> visible. - var flags = finishedWork.flags; + case OffscreenComponent: { + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(current, current.return); + } + } - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + var newState = finishedWork.memoizedState; + var isHidden = newState !== null; + var wasHidden = current !== null && current.memoizedState !== null; - if (flags & Update) { - commitHookLayoutEffects(finishedWork, Layout | HasEffect); - } + if (finishedWork.mode & ConcurrentMode) { + // Before committing the children, track on the stack whether this + // offscreen subtree was already hidden, so that we don't unmount the + // effects again. + var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden; + var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; + offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden || isHidden; + offscreenSubtreeWasHidden = + prevOffscreenSubtreeWasHidden || wasHidden; + recursivelyTraverseMutationEffects(root, finishedWork); + offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; + offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; + } else { + recursivelyTraverseMutationEffects(root, finishedWork); + } - break; - } + commitReconciliationEffects(finishedWork); + var offscreenInstance = finishedWork.stateNode; // TODO: Add explicit effect flag to set _current. - case ClassComponent: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + offscreenInstance._current = finishedWork; // Offscreen stores pending changes to visibility in `_pendingVisibility`. This is + // to support batching of `attach` and `detach` calls. - if (flags & Update) { - commitClassLayoutLifecycles(finishedWork, current); - } + offscreenInstance._visibility &= ~OffscreenDetached; + offscreenInstance._visibility |= + offscreenInstance._pendingVisibility & OffscreenDetached; - if (flags & Callback) { - commitClassCallbacks(finishedWork); - } + if (flags & Visibility) { + // Track the current state on the Offscreen instance so we can + // read it during an event + if (isHidden) { + offscreenInstance._visibility &= ~OffscreenVisible; + } else { + offscreenInstance._visibility |= OffscreenVisible; + } - if (flags & Ref) { - safelyAttachRef(finishedWork, finishedWork.return); - } + if (isHidden) { + var isUpdate = current !== null; + var wasHiddenByAncestorOffscreen = + offscreenSubtreeIsHidden || offscreenSubtreeWasHidden; // Only trigger disapper layout effects if: + // - This is an update, not first mount. + // - This Offscreen was not hidden before. + // - Ancestor Offscreen was not hidden in previous commit. + + if (isUpdate && !wasHidden && !wasHiddenByAncestorOffscreen) { + if ((finishedWork.mode & ConcurrentMode) !== NoMode) { + // Disappear the layout effects of all the children + recursivelyTraverseDisappearLayoutEffects(finishedWork); + } + } + } // Offscreen with manual mode manages visibility manually. - break; - } + if (!isOffscreenManual(finishedWork)) { + // TODO: This needs to run whenever there's an insertion or update + // inside a hidden Offscreen tree. + hideOrUnhideAllChildren(finishedWork, isHidden); + } + } // TODO: Move to passive phase - case HostRoot: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + if (flags & Update) { + var offscreenQueue = finishedWork.updateQueue; - if (flags & Callback) { - // TODO: I think this is now always non-null by the time it reaches the - // commit phase. Consider removing the type check. - var updateQueue = finishedWork.updateQueue; + if (offscreenQueue !== null) { + var _retryQueue = offscreenQueue.retryQueue; - if (updateQueue !== null) { - var instance = null; + if (_retryQueue !== null) { + offscreenQueue.retryQueue = null; + attachSuspenseRetryListeners(finishedWork, _retryQueue); + } + } + } - if (finishedWork.child !== null) { - switch (finishedWork.child.tag) { - case HostSingleton: - case HostComponent: - instance = getPublicInstance(finishedWork.child.stateNode); - break; + return; + } - case ClassComponent: - instance = finishedWork.child.stateNode; - break; + case SuspenseListComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + + if (flags & Update) { + var _retryQueue2 = finishedWork.updateQueue; + + if (_retryQueue2 !== null) { + finishedWork.updateQueue = null; + attachSuspenseRetryListeners(finishedWork, _retryQueue2); } } - try { - commitCallbacks(updateQueue, instance); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + return; + } + + case ScopeComponent: { + { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); // TODO: This is a temporary solution that allowed us to transition away + // from React Flare on www. + + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(finishedWork, finishedWork.return); + } + + safelyAttachRef(finishedWork, finishedWork.return); + } + + if (flags & Update) { + prepareScopeUpdate(); + } } + + return; } - } - break; + default: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + return; + } + } } - case HostHoistable: + function commitReconciliationEffects(finishedWork) { + // Placement effects (insertions, reorders) can be scheduled on any fiber + // type. They needs to happen after the children effects have fired, but + // before the effects on this fiber have fired. + var flags = finishedWork.flags; - case HostSingleton: - case HostComponent: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); // Renderers may schedule work to be done after host components are mounted - // (eg DOM renderer may schedule auto-focus for inputs and form controls). - // These effects should only be committed when components are first mounted, - // aka when there is no current/alternate. + if (flags & Placement) { + try { + commitPlacement(finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } // Clear the "placement" from effect tag so that we know that this is + // inserted, before any life-cycles like componentDidMount gets called. + // TODO: findDOMNode doesn't rely on this any more but isMounted does + // and isMounted is deprecated anyway so we should be able to kill this. - if (current === null && flags & Update) { - commitHostComponentMount(finishedWork); + finishedWork.flags &= ~Placement; } - if (flags & Ref) { - safelyAttachRef(finishedWork, finishedWork.return); + if (flags & Hydrating) { + finishedWork.flags &= ~Hydrating; } + } - break; + function commitLayoutEffects(finishedWork, root, committedLanes) { + inProgressLanes = committedLanes; + inProgressRoot = root; + var current = finishedWork.alternate; + commitLayoutEffectOnFiber(root, current, finishedWork); + inProgressLanes = null; + inProgressRoot = null; } - case Profiler: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); // TODO: Should this fire inside an offscreen tree? Or should it wait to - // fire when the tree becomes visible again. + function recursivelyTraverseLayoutEffects(root, parentFiber, lanes) { + var prevDebugFiber = getCurrentFiber(); + + if (parentFiber.subtreeFlags & LayoutMask) { + var child = parentFiber.child; - if (flags & Update) { - commitProfilerUpdate(finishedWork, current); + while (child !== null) { + setCurrentFiber(child); + var current = child.alternate; + commitLayoutEffectOnFiber(root, current, child); + child = child.sibling; + } } - break; + setCurrentFiber(prevDebugFiber); } - case SuspenseComponent: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - - break; - } + function disappearLayoutEffects(finishedWork) { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + // TODO (Offscreen) Check: flags & LayoutStatic + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + commitHookEffectListUnmount( + Layout, + finishedWork, + finishedWork.return + ); + } finally { + recordLayoutEffectDuration(finishedWork); + } + } else { + commitHookEffectListUnmount( + Layout, + finishedWork, + finishedWork.return + ); + } - case OffscreenComponent: { - var isModernRoot = (finishedWork.mode & ConcurrentMode) !== NoMode; + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; + } - if (isModernRoot) { - var isHidden = finishedWork.memoizedState !== null; - var newOffscreenSubtreeIsHidden = isHidden || offscreenSubtreeIsHidden; + case ClassComponent: { + // TODO (Offscreen) Check: flags & RefStatic + safelyDetachRef(finishedWork, finishedWork.return); + var instance = finishedWork.stateNode; - if (newOffscreenSubtreeIsHidden); - else { - // The Offscreen tree is visible. - var wasHidden = current !== null && current.memoizedState !== null; - var newOffscreenSubtreeWasHidden = - wasHidden || offscreenSubtreeWasHidden; - var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden; - var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; - offscreenSubtreeIsHidden = newOffscreenSubtreeIsHidden; - offscreenSubtreeWasHidden = newOffscreenSubtreeWasHidden; - - if (offscreenSubtreeWasHidden && !prevOffscreenSubtreeWasHidden) { - // This is the root of a reappearing boundary. As we continue - // traversing the layout effects, we must also re-mount layout - // effects that were unmounted when the Offscreen subtree was - // hidden. So this is a superset of the normal commitLayoutEffects. - var includeWorkInProgressEffects = - (finishedWork.subtreeFlags & LayoutMask) !== NoFlags$1; - recursivelyTraverseReappearLayoutEffects( - finishedRoot, + if (typeof instance.componentWillUnmount === "function") { + safelyCallComponentWillUnmount( finishedWork, - includeWorkInProgressEffects + finishedWork.return, + instance ); - } else { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); } - offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; - offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; } - } else { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - } - if (flags & Ref) { - var props = finishedWork.memoizedProps; + case HostHoistable: + case HostSingleton: + case HostComponent: { + // TODO (Offscreen) Check: flags & RefStatic + safelyDetachRef(finishedWork, finishedWork.return); + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; + } - if (props.mode === "manual") { - safelyAttachRef(finishedWork, finishedWork.return); - } else { + case OffscreenComponent: { + // TODO (Offscreen) Check: flags & RefStatic safelyDetachRef(finishedWork, finishedWork.return); + var isHidden = finishedWork.memoizedState !== null; + + if (isHidden); + else { + recursivelyTraverseDisappearLayoutEffects(finishedWork); + } + + break; } - } - break; + default: { + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; + } + } } - default: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - break; + function recursivelyTraverseDisappearLayoutEffects(parentFiber) { + // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) + var child = parentFiber.child; + + while (child !== null) { + disappearLayoutEffects(child); + child = child.sibling; + } } - } -} -function abortRootTransitions( - root, - abort, - deletedTransitions, - deletedOffscreenInstance, - isInDeletedTree -) { - if (enableTransitionTracing) { - var rootTransitions = root.incompleteTransitions; - deletedTransitions.forEach(function (transition) { - if (rootTransitions.has(transition)) { - var transitionInstance = rootTransitions.get(transition); + function reappearLayoutEffects( + finishedRoot, + current, + finishedWork, // This function visits both newly finished work and nodes that were re-used + // from a previously committed tree. We cannot check non-static flags if the + // node was reused. + includeWorkInProgressEffects + ) { + // Turn on layout effects in a tree that previously disappeared. + var flags = finishedWork.flags; + + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); // TODO: Check flags & LayoutStatic + + commitHookLayoutEffects(finishedWork, Layout); + break; + } + + case ClassComponent: { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); // TODO: Check for LayoutStatic flag + + var instance = finishedWork.stateNode; + + if (typeof instance.componentDidMount === "function") { + try { + instance.componentDidMount(); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } // Commit any callbacks that would have fired while the component + // was hidden. + + var updateQueue = finishedWork.updateQueue; + + if (updateQueue !== null) { + commitHiddenCallbacks(updateQueue, instance); + } // If this is newly finished work, check for setState callbacks - if (transitionInstance.aborts === null) { - transitionInstance.aborts = []; + if (includeWorkInProgressEffects && flags & Callback) { + commitClassCallbacks(finishedWork); + } // TODO: Check flags & RefStatic + + safelyAttachRef(finishedWork, finishedWork.return); + break; } + // Unlike commitLayoutEffectsOnFiber, we don't need to handle HostRoot + // because this function only visits nodes that are inside an + // Offscreen fiber. + // case HostRoot: { + // ... + // } - transitionInstance.aborts.push(abort); + case HostHoistable: + case HostSingleton: + case HostComponent: { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); // Renderers may schedule work to be done after host components are mounted + // (eg DOM renderer may schedule auto-focus for inputs and form controls). + // These effects should only be committed when components are first mounted, + // aka when there is no current/alternate. - if (deletedOffscreenInstance !== null) { if ( - transitionInstance.pendingBoundaries !== null && - transitionInstance.pendingBoundaries.has(deletedOffscreenInstance) + includeWorkInProgressEffects && + current === null && + flags & Update ) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - transitionInstance.pendingBoundaries.delete( - deletedOffscreenInstance - ); - } + commitHostComponentMount(finishedWork); + } // TODO: Check flags & Ref + + safelyAttachRef(finishedWork, finishedWork.return); + break; } - } - }); - } -} -function abortTracingMarkerTransitions( - abortedFiber, - abort, - deletedTransitions, - deletedOffscreenInstance, - isInDeletedTree -) { - if (enableTransitionTracing) { - var markerInstance = abortedFiber.stateNode; - var markerTransitions = markerInstance.transitions; - var pendingBoundaries = markerInstance.pendingBoundaries; - - if (markerTransitions !== null) { - // TODO: Refactor this code. Is there a way to move this code to - // the deletions phase instead of calculating it here while making sure - // complete is called appropriately? - deletedTransitions.forEach(function (transition) { - // If one of the transitions on the tracing marker is a transition - // that was in an aborted subtree, we will abort that tracing marker - if ( - abortedFiber !== null && - markerTransitions.has(transition) && - (markerInstance.aborts === null || - !markerInstance.aborts.includes(abort)) - ) { - if (markerInstance.transitions !== null) { - if (markerInstance.aborts === null) { - markerInstance.aborts = [abort]; - addMarkerIncompleteCallbackToPendingTransition( - abortedFiber.memoizedProps.name, - markerInstance.transitions, - markerInstance.aborts - ); - } else { - markerInstance.aborts.push(abort); - } // We only want to call onTransitionProgress when the marker hasn't been - // deleted + case Profiler: { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); // TODO: Figure out how Profiler updates should work with Offscreen - if ( - deletedOffscreenInstance !== null && - !isInDeletedTree && - pendingBoundaries !== null && - pendingBoundaries.has(deletedOffscreenInstance) - ) { - pendingBoundaries.delete(deletedOffscreenInstance); - addMarkerProgressCallbackToPendingTransition( - abortedFiber.memoizedProps.name, - deletedTransitions, - pendingBoundaries - ); - } + if (includeWorkInProgressEffects && flags & Update) { + commitProfilerUpdate(finishedWork, current); } + + break; } - }); - } - } -} -function abortParentMarkerTransitionsForDeletedFiber( - abortedFiber, - abort, - deletedTransitions, - deletedOffscreenInstance, - isInDeletedTree -) { - if (enableTransitionTracing) { - // Find all pending markers that are waiting on child suspense boundaries in the - // aborted subtree and cancels them - var fiber = abortedFiber; - - while (fiber !== null) { - switch (fiber.tag) { - case TracingMarkerComponent: - abortTracingMarkerTransitions( - fiber, - abort, - deletedTransitions, - deletedOffscreenInstance, - isInDeletedTree - ); + case SuspenseComponent: { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); // TODO: Figure out how Suspense hydration callbacks should work + break; + } - case HostRoot: - var root = fiber.stateNode; - abortRootTransitions( - root, - abort, - deletedTransitions, - deletedOffscreenInstance + case OffscreenComponent: { + var offscreenState = finishedWork.memoizedState; + var isHidden = offscreenState !== null; + + if (isHidden); + else { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); + } // TODO: Check flags & Ref + + safelyAttachRef(finishedWork, finishedWork.return); + break; + } + + default: { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects ); break; + } } - - fiber = fiber.return; } - } -} - -function commitTransitionProgress(offscreenFiber) { - if (enableTransitionTracing) { - // This function adds suspense boundaries to the root - // or tracing marker's pendingBoundaries map. - // When a suspense boundary goes from a resolved to a fallback - // state we add the boundary to the map, and when it goes from - // a fallback to a resolved state, we remove the boundary from - // the map. - // We use stateNode on the Offscreen component as a stable object - // that doesnt change from render to render. This way we can - // distinguish between different Offscreen instances (vs. the same - // Offscreen instance with different fibers) - var offscreenInstance = offscreenFiber.stateNode; - var prevState = null; - var previousFiber = offscreenFiber.alternate; - - if (previousFiber !== null && previousFiber.memoizedState !== null) { - prevState = previousFiber.memoizedState; - } - - var nextState = offscreenFiber.memoizedState; - var wasHidden = prevState !== null; - var isHidden = nextState !== null; - var pendingMarkers = offscreenInstance._pendingMarkers; // If there is a name on the suspense boundary, store that in - // the pending boundaries. - - var name = null; - var parent = offscreenFiber.return; - if ( - parent !== null && - parent.tag === SuspenseComponent && - parent.memoizedProps.unstable_name + function recursivelyTraverseReappearLayoutEffects( + finishedRoot, + parentFiber, + includeWorkInProgressEffects ) { - name = parent.memoizedProps.unstable_name; - } - - if (!wasHidden && isHidden) { - // The suspense boundaries was just hidden. Add the boundary - // to the pending boundary set if it's there - if (pendingMarkers !== null) { - pendingMarkers.forEach(function (markerInstance) { - var pendingBoundaries = markerInstance.pendingBoundaries; - var transitions = markerInstance.transitions; - var markerName = markerInstance.name; + // This function visits both newly finished work and nodes that were re-used + // from a previously committed tree. We cannot check non-static flags if the + // node was reused. + var childShouldIncludeWorkInProgressEffects = + includeWorkInProgressEffects && + (parentFiber.subtreeFlags & LayoutMask) !== NoFlags$1; // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) - if ( - pendingBoundaries !== null && - !pendingBoundaries.has(offscreenInstance) - ) { - pendingBoundaries.set(offscreenInstance, { - name: name - }); + var prevDebugFiber = getCurrentFiber(); + var child = parentFiber.child; - if (transitions !== null) { - if ( - markerInstance.tag === TransitionTracingMarker && - markerName !== null - ) { - addMarkerProgressCallbackToPendingTransition( - markerName, - transitions, - pendingBoundaries - ); - } else if (markerInstance.tag === TransitionRoot) { - transitions.forEach(function (transition) { - addTransitionProgressCallbackToPendingTransition( - transition, - pendingBoundaries - ); - }); - } - } - } - }); + while (child !== null) { + var current = child.alternate; + reappearLayoutEffects( + finishedRoot, + current, + child, + childShouldIncludeWorkInProgressEffects + ); + child = child.sibling; } - } else if (wasHidden && !isHidden) { - // The suspense boundary went from hidden to visible. Remove - // the boundary from the pending suspense boundaries set - // if it's there - if (pendingMarkers !== null) { - pendingMarkers.forEach(function (markerInstance) { - var pendingBoundaries = markerInstance.pendingBoundaries; - var transitions = markerInstance.transitions; - var markerName = markerInstance.name; - if ( - pendingBoundaries !== null && - pendingBoundaries.has(offscreenInstance) - ) { - pendingBoundaries.delete(offscreenInstance); + setCurrentFiber(prevDebugFiber); + } - if (transitions !== null) { - if ( - markerInstance.tag === TransitionTracingMarker && - markerName !== null - ) { - addMarkerProgressCallbackToPendingTransition( - markerName, - transitions, - pendingBoundaries - ); // If there are no more unresolved suspense boundaries, the interaction - // is considered finished + function commitHookPassiveMountEffects(finishedWork, hookFlags) { + if (shouldProfile(finishedWork)) { + startPassiveEffectTimer(); - if (pendingBoundaries.size === 0) { - if (markerInstance.aborts === null) { - addMarkerCompleteCallbackToPendingTransition( - markerName, - transitions - ); - } + try { + commitHookEffectListMount(hookFlags, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } - markerInstance.transitions = null; - markerInstance.pendingBoundaries = null; - markerInstance.aborts = null; - } - } else if (markerInstance.tag === TransitionRoot) { - transitions.forEach(function (transition) { - addTransitionProgressCallbackToPendingTransition( - transition, - pendingBoundaries - ); - }); - } - } - } - }); + recordPassiveEffectDuration(finishedWork); + } else { + try { + commitHookEffectListMount(hookFlags, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } } } - } -} -function hideOrUnhideAllChildren(finishedWork, isHidden) { - // Only hide or unhide the top-most host nodes. - var hostSubtreeRoot = null; - - { - // We only have the top Fiber that was inserted but we need to recurse down its - // children to find all the terminal nodes. - var node = finishedWork; + function commitOffscreenPassiveMountEffects( + current, + finishedWork, + instance + ) { + { + var previousCache = null; - while (true) { - if (node.tag === HostComponent || false || false) { - if (hostSubtreeRoot === null) { - hostSubtreeRoot = node; + if ( + current !== null && + current.memoizedState !== null && + current.memoizedState.cachePool !== null + ) { + previousCache = current.memoizedState.cachePool.pool; + } - try { - var instance = node.stateNode; + var nextCache = null; - if (isHidden) { - hideInstance(instance); - } else { - unhideInstance(node.stateNode, node.memoizedProps); - } - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + if ( + finishedWork.memoizedState !== null && + finishedWork.memoizedState.cachePool !== null + ) { + nextCache = finishedWork.memoizedState.cachePool.pool; + } // Retain/release the cache used for pending (suspended) nodes. + // Note that this is only reached in the non-suspended/visible case: + // when the content is suspended/hidden, the retain/release occurs + // via the parent Suspense component (see case above). + + if (nextCache !== previousCache) { + if (nextCache != null) { + retainCache(nextCache); } - } - } else if (node.tag === HostText) { - if (hostSubtreeRoot === null) { - try { - var _instance = node.stateNode; - if (isHidden) { - hideTextInstance(_instance); - } else { - unhideTextInstance(_instance, node.memoizedProps); - } - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + if (previousCache != null) { + releaseCache(previousCache); } } - } else if ( - (node.tag === OffscreenComponent || - node.tag === LegacyHiddenComponent) && - node.memoizedState !== null && - node !== finishedWork - ); - else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; } - if (node === finishedWork) { - return; - } + if (enableTransitionTracing) { + // TODO: Pre-rendering should not be counted as part of a transition. We + // may add separate logs for pre-rendering, but it's not part of the + // primary metrics. + var offscreenState = finishedWork.memoizedState; + var queue = finishedWork.updateQueue; + var isHidden = offscreenState !== null; - while (node.sibling === null) { - if (node.return === null || node.return === finishedWork) { - return; - } + if (queue !== null) { + if (isHidden) { + var transitions = queue.transitions; - if (hostSubtreeRoot === node) { - hostSubtreeRoot = null; - } + if (transitions !== null) { + transitions.forEach(function (transition) { + // Add all the transitions saved in the update queue during + // the render phase (ie the transitions associated with this boundary) + // into the transitions set. + if (instance._transitions === null) { + instance._transitions = new Set(); + } - node = node.return; - } + instance._transitions.add(transition); + }); + } - if (hostSubtreeRoot === node) { - hostSubtreeRoot = null; - } + var markerInstances = queue.markerInstances; - node.sibling.return = node.return; - node = node.sibling; - } - } -} + if (markerInstances !== null) { + markerInstances.forEach(function (markerInstance) { + var markerTransitions = markerInstance.transitions; // There should only be a few tracing marker transitions because + // they should be only associated with the transition that + // caused them -function commitAttachRef(finishedWork) { - var ref = finishedWork.ref; + if (markerTransitions !== null) { + markerTransitions.forEach(function (transition) { + if (instance._transitions === null) { + instance._transitions = new Set(); + } else if (instance._transitions.has(transition)) { + if (markerInstance.pendingBoundaries === null) { + markerInstance.pendingBoundaries = new Map(); + } - if (ref !== null) { - var instance = finishedWork.stateNode; - var instanceToUse; + if (instance._pendingMarkers === null) { + instance._pendingMarkers = new Set(); + } - switch (finishedWork.tag) { - case HostHoistable: - case HostSingleton: - case HostComponent: - instanceToUse = getPublicInstance(instance); - break; + instance._pendingMarkers.add(markerInstance); + } + }); + } + }); + } + } - default: - instanceToUse = instance; - } // Moved outside to ensure DCE works with this flag + finishedWork.updateQueue = null; + } - if (finishedWork.tag === ScopeComponent) { - instanceToUse = instance; - } + commitTransitionProgress(finishedWork); // TODO: Refactor this into an if/else branch - if (typeof ref === "function") { - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - finishedWork.refCleanup = ref(instanceToUse); - } finally { - recordLayoutEffectDuration(finishedWork); + if (!isHidden) { + instance._transitions = null; + instance._pendingMarkers = null; } - } else { - finishedWork.refCleanup = ref(instanceToUse); } - } else { - { - if (!ref.hasOwnProperty("current")) { - error( - "Unexpected ref object provided for %s. " + - "Use either a ref-setter function or React.createRef().", - getComponentNameFromFiber(finishedWork) - ); - } - } // $FlowFixMe[incompatible-use] unable to narrow type to the non-function case - - ref.current = instanceToUse; } - } -} -function detachFiberMutation(fiber) { - // Cut off the return pointer to disconnect it from the tree. - // This enables us to detect and warn against state updates on an unmounted component. - // It also prevents events from bubbling from within disconnected components. - // - // Ideally, we should also clear the child pointer of the parent alternate to let this - // get GC:ed but we don't know which for sure which parent is the current - // one so we'll settle for GC:ing the subtree of this child. - // This child itself will be GC:ed when the parent updates the next time. - // - // Note that we can't clear child or sibling pointers yet. - // They're needed for passive effects and for findDOMNode. - // We defer those fields, and all other cleanup, to the passive phase (see detachFiberAfterEffects). - // - // Don't reset the alternate yet, either. We need that so we can detach the - // alternate's fields in the passive phase. Clearing the return pointer is - // sufficient for findDOMNode semantics. - var alternate = fiber.alternate; - - if (alternate !== null) { - alternate.return = null; - } - - fiber.return = null; -} - -function detachFiberAfterEffects(fiber) { - var alternate = fiber.alternate; - - if (alternate !== null) { - fiber.alternate = null; - detachFiberAfterEffects(alternate); - } // Clear cyclical Fiber fields. This level alone is designed to roughly - // approximate the planned Fiber refactor. In that world, `setState` will be - // bound to a special "instance" object instead of a Fiber. The Instance - // object will not have any of these fields. It will only be connected to - // the fiber tree via a single link at the root. So if this level alone is - // sufficient to fix memory issues, that bodes well for our plans. - - fiber.child = null; - fiber.deletions = null; - fiber.sibling = null; // The `stateNode` is cyclical because on host nodes it points to the host - - fiber.stateNode = null; - - { - fiber._debugSource = null; - fiber._debugOwner = null; - } // Theoretically, nothing in here should be necessary, because we already - // disconnected the fiber from the tree. So even if something leaks this - // particular fiber, it won't leak anything else. - - fiber.return = null; - fiber.dependencies = null; - fiber.memoizedProps = null; - fiber.memoizedState = null; - fiber.pendingProps = null; - fiber.stateNode = null; // TODO: Move to `commitPassiveUnmountInsideDeletedTreeOnFiber` instead. - - fiber.updateQueue = null; -} - -function getHostParentFiber(fiber) { - var parent = fiber.return; + function commitCachePassiveMountEffect(current, finishedWork) { + { + var previousCache = null; - while (parent !== null) { - if (isHostParent(parent)) { - return parent; - } + if (finishedWork.alternate !== null) { + previousCache = finishedWork.alternate.memoizedState.cache; + } - parent = parent.return; - } + var nextCache = finishedWork.memoizedState.cache; // Retain/release the cache. In theory the cache component + // could be "borrowing" a cache instance owned by some parent, + // in which case we could avoid retaining/releasing. But it + // is non-trivial to determine when that is the case, so we + // always retain/release. - throw new Error( - "Expected to find a host parent. This error is likely caused by a bug " + - "in React. Please file an issue." - ); -} + if (nextCache !== previousCache) { + retainCache(nextCache); -function isHostParent(fiber) { - return ( - fiber.tag === HostComponent || - fiber.tag === HostRoot || - false || - false || - fiber.tag === HostPortal - ); -} + if (previousCache != null) { + releaseCache(previousCache); + } + } + } + } -function getHostSibling(fiber) { - // We're going to search forward into the tree until we find a sibling host - // node. Unfortunately, if multiple insertions are done in a row we have to - // search past them. This leads to exponential search for the next sibling. - // TODO: Find a more efficient way to do this. - var node = fiber; - - siblings: while (true) { - // If we didn't find anything, let's try the next sibling. - while (node.sibling === null) { - if (node.return === null || isHostParent(node.return)) { - // If we pop out of the root or hit the parent the fiber we are the - // last sibling. - return null; - } // $FlowFixMe[incompatible-type] found when upgrading Flow + function commitTracingMarkerPassiveMountEffect(finishedWork) { + // Get the transitions that were initiatized during the render + // and add a start transition callback for each of them + // We will only call this on initial mount of the tracing marker + // only if there are no suspense children + var instance = finishedWork.stateNode; - node = node.return; + if ( + instance.transitions !== null && + instance.pendingBoundaries === null + ) { + addMarkerCompleteCallbackToPendingTransition( + finishedWork.memoizedProps.name, + instance.transitions + ); + instance.transitions = null; + instance.pendingBoundaries = null; + instance.aborts = null; + instance.name = null; + } } - node.sibling.return = node.return; - node = node.sibling; + function commitPassiveMountEffects( + root, + finishedWork, + committedLanes, + committedTransitions + ) { + setCurrentFiber(finishedWork); + commitPassiveMountOnFiber( + root, + finishedWork, + committedLanes, + committedTransitions + ); + resetCurrentFiber(); + } - while ( - node.tag !== HostComponent && - node.tag !== HostText && - true && - node.tag !== DehydratedFragment + function recursivelyTraversePassiveMountEffects( + root, + parentFiber, + committedLanes, + committedTransitions ) { - // If it is not host node and, we might have a host node inside it. - // Try to search down until we find one. - if (node.flags & Placement) { - // If we don't have a child, try the siblings instead. - continue siblings; - } // If we don't have a child, try the siblings instead. - // We also skip portals because they are not part of this host tree. - - if (node.child === null || node.tag === HostPortal) { - continue siblings; - } else { - node.child.return = node; - node = node.child; + var prevDebugFiber = getCurrentFiber(); + + if (parentFiber.subtreeFlags & PassiveMask) { + var child = parentFiber.child; + + while (child !== null) { + setCurrentFiber(child); + commitPassiveMountOnFiber( + root, + child, + committedLanes, + committedTransitions + ); + child = child.sibling; + } } - } // Check if this host node is stable or about to be placed. - if (!(node.flags & Placement)) { - // Found it! - return node.stateNode; + setCurrentFiber(prevDebugFiber); } - } -} -function commitPlacement(finishedWork) { - var parentFiber = getHostParentFiber(finishedWork); + function commitPassiveMountOnFiber( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ) { + // When updating this function, also update reconnectPassiveEffects, which does + // most of the same things when an offscreen tree goes from hidden -> visible, + // or when toggling effects inside a hidden tree. + var flags = finishedWork.flags; - switch (parentFiber.tag) { - case HostSingleton: + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); - case HostComponent: { - var _parent = parentFiber.stateNode; + if (flags & Passive$1) { + commitHookPassiveMountEffects(finishedWork, Passive | HasEffect); + } - if (parentFiber.flags & ContentReset) { - parentFiber.flags &= ~ContentReset; - } + break; + } - var _before = getHostSibling(finishedWork); // We only have the top Fiber that was inserted but we need to recurse down its - // children to find all the terminal nodes. + case HostRoot: { + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); - insertOrAppendPlacementNode(finishedWork, _before, _parent); - break; - } + if (flags & Passive$1) { + { + var previousCache = null; - case HostRoot: - case HostPortal: { - var _parent2 = parentFiber.stateNode.containerInfo; + if (finishedWork.alternate !== null) { + previousCache = finishedWork.alternate.memoizedState.cache; + } - var _before2 = getHostSibling(finishedWork); + var nextCache = finishedWork.memoizedState.cache; // Retain/release the root cache. + // Note that on initial mount, previousCache and nextCache will be the same + // and this retain won't occur. To counter this, we instead retain the HostRoot's + // initial cache when creating the root itself (see createFiberRoot() in + // ReactFiberRoot.js). Subsequent updates that change the cache are reflected + // here, such that previous/next caches are retained correctly. - insertOrAppendPlacementNodeIntoContainer( - finishedWork, - _before2, - _parent2 - ); - break; - } + if (nextCache !== previousCache) { + retainCache(nextCache); - default: - throw new Error( - "Invalid host parent fiber. This error is likely caused by a bug " + - "in React. Please file an issue." - ); - } -} + if (previousCache != null) { + releaseCache(previousCache); + } + } + } -function insertOrAppendPlacementNodeIntoContainer(node, before, parent) { - var tag = node.tag; - var isHost = tag === HostComponent || tag === HostText; + if (enableTransitionTracing) { + // Get the transitions that were initiatized during the render + // and add a start transition callback for each of them + var root = finishedWork.stateNode; + var incompleteTransitions = root.incompleteTransitions; // Initial render - if (isHost) { - var stateNode = node.stateNode; + if (committedTransitions !== null) { + committedTransitions.forEach(function (transition) { + addTransitionStartCallbackToPendingTransition(transition); + }); + clearTransitionsForLanes(finishedRoot, committedLanes); + } - if (before) { - insertInContainerBefore(parent, stateNode, before); - } else { - appendChildToContainer(parent, stateNode); - } - } else if (tag === HostPortal || false); - else { - var child = node.child; + incompleteTransitions.forEach( + function (markerInstance, transition) { + var pendingBoundaries = markerInstance.pendingBoundaries; + + if ( + pendingBoundaries === null || + pendingBoundaries.size === 0 + ) { + if (markerInstance.aborts === null) { + addTransitionCompleteCallbackToPendingTransition( + transition + ); + } - if (child !== null) { - insertOrAppendPlacementNodeIntoContainer(child, before, parent); - var sibling = child.sibling; + incompleteTransitions.delete(transition); + } + } + ); + clearTransitionsForLanes(finishedRoot, committedLanes); + } + } - while (sibling !== null) { - insertOrAppendPlacementNodeIntoContainer(sibling, before, parent); - sibling = sibling.sibling; - } - } - } -} + break; + } -function insertOrAppendPlacementNode(node, before, parent) { - var tag = node.tag; - var isHost = tag === HostComponent || tag === HostText; + case LegacyHiddenComponent: { + { + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); - if (isHost) { - var stateNode = node.stateNode; + if (flags & Passive$1) { + var current = finishedWork.alternate; + var instance = finishedWork.stateNode; + commitOffscreenPassiveMountEffects( + current, + finishedWork, + instance + ); + } + } - if (before) { - insertBefore(parent, stateNode, before); - } else { - appendChild(parent, stateNode); - } - } else if (tag === HostPortal || false); - else { - var child = node.child; - - if (child !== null) { - insertOrAppendPlacementNode(child, before, parent); - var sibling = child.sibling; - - while (sibling !== null) { - insertOrAppendPlacementNode(sibling, before, parent); - sibling = sibling.sibling; - } - } - } -} // These are tracked on the stack as we recursively traverse a -// deleted subtree. -// TODO: Update these during the whole mutation phase, not just during -// a deletion. - -var hostParent = null; -var hostParentIsContainer = false; - -function commitDeletionEffects(root, returnFiber, deletedFiber) { - { - // We only have the top Fiber that was deleted but we need to recurse down its - // children to find all the terminal nodes. - // Recursively delete all host nodes from the parent, detach refs, clean - // up mounted layout effects, and call componentWillUnmount. - // We only need to remove the topmost host child in each branch. But then we - // still need to keep traversing to unmount effects, refs, and cWU. TODO: We - // could split this into two separate traversals functions, where the second - // one doesn't include any removeChild logic. This is maybe the same - // function as "disappearLayoutEffects" (or whatever that turns into after - // the layout phase is refactored to use recursion). - // Before starting, find the nearest host parent on the stack so we know - // which instance/container to remove the children from. - // TODO: Instead of searching up the fiber return path on every deletion, we - // can track the nearest host component on the JS stack as we traverse the - // tree during the commit phase. This would make insertions faster, too. - var parent = returnFiber; - - findParent: while (parent !== null) { - switch (parent.tag) { - case HostSingleton: - case HostComponent: { - hostParent = parent.stateNode; - hostParentIsContainer = false; - break findParent; + break; } - case HostRoot: { - hostParent = parent.stateNode.containerInfo; - hostParentIsContainer = true; - break findParent; - } + case OffscreenComponent: { + // TODO: Pass `current` as argument to this function + var _instance3 = finishedWork.stateNode; + var nextState = finishedWork.memoizedState; + var isHidden = nextState !== null; + + if (isHidden) { + if (_instance3._visibility & OffscreenPassiveEffectsConnected) { + // The effects are currently connected. Update them. + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); + } else { + if (finishedWork.mode & ConcurrentMode) { + // The effects are currently disconnected. Since the tree is hidden, + // don't connect them. This also applies to the initial render. + { + // "Atomic" effects are ones that need to fire on every commit, + // even during pre-rendering. An example is updating the reference + // count on cache instances. + recursivelyTraverseAtomicPassiveEffects( + finishedRoot, + finishedWork + ); + } + } else { + // Legacy Mode: Fire the effects even if the tree is hidden. + _instance3._visibility |= OffscreenPassiveEffectsConnected; + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); + } + } + } else { + // Tree is visible + if (_instance3._visibility & OffscreenPassiveEffectsConnected) { + // The effects are currently connected. Update them. + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); + } else { + // The effects are currently disconnected. Reconnect them, while also + // firing effects inside newly mounted trees. This also applies to + // the initial render. + _instance3._visibility |= OffscreenPassiveEffectsConnected; + var includeWorkInProgressEffects = + (finishedWork.subtreeFlags & PassiveMask) !== NoFlags$1; + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); + } + } - case HostPortal: { - hostParent = parent.stateNode.containerInfo; - hostParentIsContainer = true; - break findParent; + if (flags & Passive$1) { + var _current = finishedWork.alternate; + commitOffscreenPassiveMountEffects( + _current, + finishedWork, + _instance3 + ); + } + + break; } - } - parent = parent.return; - } + case CacheComponent: { + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); - if (hostParent === null) { - throw new Error( - "Expected to find a host parent. This error is likely caused by " + - "a bug in React. Please file an issue." - ); - } + if (flags & Passive$1) { + // TODO: Pass `current` as argument to this function + var _current2 = finishedWork.alternate; + commitCachePassiveMountEffect(_current2, finishedWork); + } - commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber); - hostParent = null; - hostParentIsContainer = false; - } + break; + } - detachFiberMutation(deletedFiber); -} + case TracingMarkerComponent: { + if (enableTransitionTracing) { + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); -function recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - parent -) { - // TODO: Use a static flag to skip trees that don't have unmount effects - var child = parent.child; - - while (child !== null) { - commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, child); - child = child.sibling; - } -} + if (flags & Passive$1) { + commitTracingMarkerPassiveMountEffect(finishedWork); + } -function commitDeletionEffectsOnFiber( - finishedRoot, - nearestMountedAncestor, - deletedFiber -) { - onCommitUnmount(deletedFiber); // The cases in this outer switch modify the stack before they traverse - // into their subtree. There are simpler cases in the inner switch - // that don't modify the stack. + break; + } // Intentional fallthrough to next branch + } - switch (deletedFiber.tag) { - case HostHoistable: + default: { + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); + break; + } + } + } - case HostSingleton: + function recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + parentFiber, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ) { + // This function visits both newly finished work and nodes that were re-used + // from a previously committed tree. We cannot check non-static flags if the + // node was reused. + var childShouldIncludeWorkInProgressEffects = + includeWorkInProgressEffects && + (parentFiber.subtreeFlags & PassiveMask) !== NoFlags$1; // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) - case HostComponent: { - if (!offscreenSubtreeWasHidden) { - safelyDetachRef(deletedFiber, nearestMountedAncestor); - } // Intentional fallthrough to next branch - } + var prevDebugFiber = getCurrentFiber(); + var child = parentFiber.child; - case HostText: { - // We only need to remove the nearest host child. Set the host parent - // to `null` on the stack to indicate that nested children don't - // need to be removed. - { - var _prevHostParent = hostParent; - var _prevHostParentIsContainer = hostParentIsContainer; - hostParent = null; - recursivelyTraverseDeletionEffects( + while (child !== null) { + reconnectPassiveEffects( finishedRoot, - nearestMountedAncestor, - deletedFiber + child, + committedLanes, + committedTransitions, + childShouldIncludeWorkInProgressEffects ); - hostParent = _prevHostParent; - hostParentIsContainer = _prevHostParentIsContainer; - - if (hostParent !== null) { - // Now that all the child effects have unmounted, we can remove the - // node from the tree. - if (hostParentIsContainer) { - removeChildFromContainer(hostParent, deletedFiber.stateNode); - } else { - removeChild(hostParent, deletedFiber.stateNode); - } - } + child = child.sibling; } - return; + setCurrentFiber(prevDebugFiber); } - case DehydratedFragment: { - { - var hydrationCallbacks = finishedRoot.hydrationCallbacks; + function reconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, // This function visits both newly finished work and nodes that were re-used + // from a previously committed tree. We cannot check non-static flags if the + // node was reused. + includeWorkInProgressEffects + ) { + var flags = finishedWork.flags; - if (hydrationCallbacks !== null) { - var onDeleted = hydrationCallbacks.onDeleted; + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); // TODO: Check for PassiveStatic flag - if (onDeleted) { - onDeleted(deletedFiber.stateNode); - } + commitHookPassiveMountEffects(finishedWork, Passive); + break; } - } // Dehydrated fragments don't have any children - // Delete the dehydrated suspense boundary and all of its content. + // Unlike commitPassiveMountOnFiber, we don't need to handle HostRoot + // because this function only visits nodes that are inside an + // Offscreen fiber. + // case HostRoot: { + // ... + // } - { - if (hostParent !== null) { - if (hostParentIsContainer) { - clearSuspenseBoundaryFromContainer(); - } else { - clearSuspenseBoundary(); + case LegacyHiddenComponent: { + { + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); + + if (includeWorkInProgressEffects && flags & Passive$1) { + // TODO: Pass `current` as argument to this function + var current = finishedWork.alternate; + var instance = finishedWork.stateNode; + commitOffscreenPassiveMountEffects( + current, + finishedWork, + instance + ); + } } + + break; } - } - return; - } + case OffscreenComponent: { + var _instance4 = finishedWork.stateNode; + var nextState = finishedWork.memoizedState; + var isHidden = nextState !== null; + + if (isHidden) { + if (_instance4._visibility & OffscreenPassiveEffectsConnected) { + // The effects are currently connected. Update them. + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); + } else { + if (finishedWork.mode & ConcurrentMode) { + // The effects are currently disconnected. Since the tree is hidden, + // don't connect them. This also applies to the initial render. + { + // "Atomic" effects are ones that need to fire on every commit, + // even during pre-rendering. An example is updating the reference + // count on cache instances. + recursivelyTraverseAtomicPassiveEffects( + finishedRoot, + finishedWork + ); + } + } else { + // Legacy Mode: Fire the effects even if the tree is hidden. + _instance4._visibility |= OffscreenPassiveEffectsConnected; + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); + } + } + } else { + // Tree is visible + // Since we're already inside a reconnecting tree, it doesn't matter + // whether the effects are currently connected. In either case, we'll + // continue traversing the tree and firing all the effects. + // + // We do need to set the "connected" flag on the instance, though. + _instance4._visibility |= OffscreenPassiveEffectsConnected; + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); + } - case HostPortal: { - { - // When we go into a portal, it becomes the parent to remove from. - var _prevHostParent2 = hostParent; - var _prevHostParentIsContainer2 = hostParentIsContainer; - hostParent = deletedFiber.stateNode.containerInfo; - hostParentIsContainer = true; - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - hostParent = _prevHostParent2; - hostParentIsContainer = _prevHostParentIsContainer2; - } + if (includeWorkInProgressEffects && flags & Passive$1) { + // TODO: Pass `current` as argument to this function + var _current3 = finishedWork.alternate; + commitOffscreenPassiveMountEffects( + _current3, + finishedWork, + _instance4 + ); + } - return; - } + break; + } - case FunctionComponent: - case ForwardRef: - case MemoComponent: - case SimpleMemoComponent: { - if (!offscreenSubtreeWasHidden) { - var updateQueue = deletedFiber.updateQueue; + case CacheComponent: { + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); - if (updateQueue !== null) { - var lastEffect = updateQueue.lastEffect; + if (includeWorkInProgressEffects && flags & Passive$1) { + // TODO: Pass `current` as argument to this function + var _current4 = finishedWork.alternate; + commitCachePassiveMountEffect(_current4, finishedWork); + } - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; + break; + } - do { - var tag = effect.tag; - var inst = effect.inst; - var destroy = inst.destroy; - - if (destroy !== undefined) { - if ((tag & Insertion) !== NoFlags) { - inst.destroy = undefined; - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - ); - } else if ((tag & Layout) !== NoFlags) { - if (enableSchedulingProfiler) { - markComponentLayoutEffectUnmountStarted(deletedFiber); - } + case TracingMarkerComponent: { + if (enableTransitionTracing) { + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); - if (shouldProfile(deletedFiber)) { - startLayoutEffectTimer(); - inst.destroy = undefined; - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - ); - recordLayoutEffectDuration(deletedFiber); - } else { - inst.destroy = undefined; - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - ); - } + if (includeWorkInProgressEffects && flags & Passive$1) { + commitTracingMarkerPassiveMountEffect(finishedWork); + } - if (enableSchedulingProfiler) { - markComponentLayoutEffectUnmountStopped(); - } - } - } + break; + } // Intentional fallthrough to next branch + } - effect = effect.next; - } while (effect !== firstEffect); - } + default: { + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); + break; } } - - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; } - case ClassComponent: { - if (!offscreenSubtreeWasHidden) { - safelyDetachRef(deletedFiber, nearestMountedAncestor); - var instance = deletedFiber.stateNode; + function recursivelyTraverseAtomicPassiveEffects( + finishedRoot, + parentFiber, + committedLanes, + committedTransitions + ) { + // "Atomic" effects are ones that need to fire on every commit, even during + // pre-rendering. We call this function when traversing a hidden tree whose + // regular effects are currently disconnected. + var prevDebugFiber = getCurrentFiber(); // TODO: Add special flag for atomic effects - if (typeof instance.componentWillUnmount === "function") { - safelyCallComponentWillUnmount( - deletedFiber, - nearestMountedAncestor, - instance - ); + if (parentFiber.subtreeFlags & PassiveMask) { + var child = parentFiber.child; + + while (child !== null) { + setCurrentFiber(child); + commitAtomicPassiveEffects(finishedRoot, child); + child = child.sibling; } } - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; + setCurrentFiber(prevDebugFiber); } - case ScopeComponent: { - { - safelyDetachRef(deletedFiber, nearestMountedAncestor); - } - - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; - } - - case OffscreenComponent: { - safelyDetachRef(deletedFiber, nearestMountedAncestor); - - if (deletedFiber.mode & ConcurrentMode) { - // If this offscreen component is hidden, we already unmounted it. Before - // deleting the children, track that it's already unmounted so that we - // don't attempt to unmount the effects again. - // TODO: If the tree is hidden, in most cases we should be able to skip - // over the nested children entirely. An exception is we haven't yet found - // the topmost host node to delete, which we already track on the stack. - // But the other case is portals, which need to be detached no matter how - // deeply they are nested. We should use a subtree flag to track whether a - // subtree includes a nested portal. - var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; - offscreenSubtreeWasHidden = - prevOffscreenSubtreeWasHidden || deletedFiber.memoizedState !== null; - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; - } else { - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - } + function commitAtomicPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ) { + // "Atomic" effects are ones that need to fire on every commit, even during + // pre-rendering. We call this function when traversing a hidden tree whose + // regular effects are currently disconnected. + var flags = finishedWork.flags; - break; - } + switch (finishedWork.tag) { + case OffscreenComponent: { + recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork); + + if (flags & Passive$1) { + // TODO: Pass `current` as argument to this function + var current = finishedWork.alternate; + var instance = finishedWork.stateNode; + commitOffscreenPassiveMountEffects(current, finishedWork, instance); + } - default: { - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; - } - } -} + break; + } -function commitSuspenseCallback(finishedWork) { - // TODO: Move this to passive phase - var newState = finishedWork.memoizedState; + case CacheComponent: { + recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork); - if (newState !== null) { - var suspenseCallback = finishedWork.memoizedProps.suspenseCallback; + if (flags & Passive$1) { + // TODO: Pass `current` as argument to this function + var _current5 = finishedWork.alternate; + commitCachePassiveMountEffect(_current5, finishedWork); + } - if (typeof suspenseCallback === "function") { - var retryQueue = finishedWork.updateQueue; + break; + } - if (retryQueue !== null) { - suspenseCallback(new Set(retryQueue)); - } - } else { - if (suspenseCallback !== undefined) { - error("Unexpected type for suspenseCallback."); + default: { + recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork); + break; + } } } - } -} -function getRetryCache(finishedWork) { - // TODO: Unify the interface for the retry cache so we don't have to switch - // on the tag like this. - switch (finishedWork.tag) { - case SuspenseComponent: - case SuspenseListComponent: { - var retryCache = finishedWork.stateNode; - - if (retryCache === null) { - retryCache = finishedWork.stateNode = new PossiblyWeakSet(); - } + function commitPassiveUnmountEffects(finishedWork) { + setCurrentFiber(finishedWork); + commitPassiveUnmountOnFiber(finishedWork); + resetCurrentFiber(); + } // If we're inside a brand new tree, or a tree that was already visible, then we + // should only suspend host components that have a ShouldSuspendCommit flag. + // Components without it haven't changed since the last commit, so we can skip + // over those. + // + // When we enter a tree that is being revealed (going from hidden -> visible), + // we need to suspend _any_ component that _may_ suspend. Even if they're + // already in the "current" tree. Because their visibility has changed, the + // browser may not have prerendered them yet. So we check the MaySuspendCommit + // flag instead. - return retryCache; + var suspenseyCommitFlag = ShouldSuspendCommit; + function accumulateSuspenseyCommit(finishedWork) { + accumulateSuspenseyCommitOnFiber(finishedWork); } - case OffscreenComponent: { - var instance = finishedWork.stateNode; - var _retryCache = instance._retryCache; + function recursivelyAccumulateSuspenseyCommit(parentFiber) { + if (parentFiber.subtreeFlags & suspenseyCommitFlag) { + var child = parentFiber.child; - if (_retryCache === null) { - _retryCache = instance._retryCache = new PossiblyWeakSet(); + while (child !== null) { + accumulateSuspenseyCommitOnFiber(child); + child = child.sibling; + } } - - return _retryCache; - } - - default: { - throw new Error( - "Unexpected Suspense handler tag (" + - finishedWork.tag + - "). This is a " + - "bug in React." - ); } - } -} -function detachOffscreenInstance(instance) { - var fiber = instance._current; + function accumulateSuspenseyCommitOnFiber(fiber) { + switch (fiber.tag) { + case HostHoistable: { + recursivelyAccumulateSuspenseyCommit(fiber); - if (fiber === null) { - throw new Error( - "Calling Offscreen.detach before instance handle has been set." - ); - } + if (fiber.flags & suspenseyCommitFlag) { + if (fiber.memoizedState !== null) { + suspendResource(); + } + } - if ((instance._pendingVisibility & OffscreenDetached) !== NoFlags$1) { - // The instance is already detached, this is a noop. - return; - } // TODO: There is an opportunity to optimise this by not entering commit phase - // and unmounting effects directly. + break; + } - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + case HostComponent: { + recursivelyAccumulateSuspenseyCommit(fiber); - if (root !== null) { - instance._pendingVisibility |= OffscreenDetached; - scheduleUpdateOnFiber(root, fiber, SyncLane); - } -} -function attachOffscreenInstance(instance) { - var fiber = instance._current; + break; + } - if (fiber === null) { - throw new Error( - "Calling Offscreen.detach before instance handle has been set." - ); - } + case HostRoot: + case HostPortal: { + { + recursivelyAccumulateSuspenseyCommit(fiber); + } - if ((instance._pendingVisibility & OffscreenDetached) === NoFlags$1) { - // The instance is already attached, this is a noop. - return; - } + break; + } - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + case OffscreenComponent: { + var isHidden = fiber.memoizedState !== null; - if (root !== null) { - instance._pendingVisibility &= ~OffscreenDetached; - scheduleUpdateOnFiber(root, fiber, SyncLane); - } -} + if (isHidden); + else { + var current = fiber.alternate; + var wasHidden = current !== null && current.memoizedState !== null; -function attachSuspenseRetryListeners(finishedWork, wakeables) { - // If this boundary just timed out, then it will have a set of wakeables. - // For each wakeable, attach a listener so that when it resolves, React - // attempts to re-render the boundary in the primary (pre-timeout) state. - var retryCache = getRetryCache(finishedWork); - wakeables.forEach(function (wakeable) { - // Memoize using the boundary fiber to prevent redundant listeners. - var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); + if (wasHidden) { + // This tree is being revealed. Visit all newly visible suspensey + // instances, even if they're in the current tree. + var prevFlags = suspenseyCommitFlag; + suspenseyCommitFlag = MaySuspendCommit; + recursivelyAccumulateSuspenseyCommit(fiber); + suspenseyCommitFlag = prevFlags; + } else { + recursivelyAccumulateSuspenseyCommit(fiber); + } + } - if (!retryCache.has(wakeable)) { - retryCache.add(wakeable); + break; + } - { - if (isDevToolsPresent) { - if (inProgressLanes !== null && inProgressRoot !== null) { - // If we have pending work still, associate the original updaters with it. - restorePendingUpdaters(inProgressRoot, inProgressLanes); - } else { - throw Error( - "Expected finished root and lanes to be set. This is a bug in React." - ); - } + default: { + recursivelyAccumulateSuspenseyCommit(fiber); } } - - wakeable.then(retry, retry); } - }); -} // This function detects when a Suspense boundary goes from visible to hidden. -// It returns false if the boundary is already hidden. -// TODO: Use an effect tag. - -function isSuspenseBoundaryBeingHidden(current, finishedWork) { - if (current !== null) { - var oldState = current.memoizedState; - if (oldState === null || oldState.dehydrated !== null) { - var newState = finishedWork.memoizedState; - return newState !== null && newState.dehydrated === null; - } - } + function detachAlternateSiblings(parentFiber) { + // A fiber was deleted from this parent fiber, but it's still part of the + // previous (alternate) parent fiber's list of children. Because children + // are a linked list, an earlier sibling that's still alive will be + // connected to the deleted fiber via its `alternate`: + // + // live fiber --alternate--> previous live fiber --sibling--> deleted + // fiber + // + // We can't disconnect `alternate` on nodes that haven't been deleted yet, + // but we can disconnect the `sibling` and `child` pointers. + var previousFiber = parentFiber.alternate; - return false; -} -function commitMutationEffects(root, finishedWork, committedLanes) { - inProgressLanes = committedLanes; - inProgressRoot = root; - setCurrentFiber(finishedWork); - commitMutationEffectsOnFiber(finishedWork, root); - setCurrentFiber(finishedWork); - inProgressLanes = null; - inProgressRoot = null; -} + if (previousFiber !== null) { + var detachedChild = previousFiber.child; -function recursivelyTraverseMutationEffects(root, parentFiber, lanes) { - // Deletions effects can be scheduled on any fiber type. They need to happen - // before the children effects hae fired. - var deletions = parentFiber.deletions; + if (detachedChild !== null) { + previousFiber.child = null; - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var childToDelete = deletions[i]; + do { + // $FlowFixMe[incompatible-use] found when upgrading Flow + var detachedSibling = detachedChild.sibling; // $FlowFixMe[incompatible-use] found when upgrading Flow - try { - commitDeletionEffects(root, parentFiber, childToDelete); - } catch (error) { - captureCommitPhaseError(childToDelete, parentFiber, error); + detachedChild.sibling = null; + detachedChild = detachedSibling; + } while (detachedChild !== null); + } } } - } - - var prevDebugFiber = getCurrentFiber(); - - if (parentFiber.subtreeFlags & MutationMask) { - var child = parentFiber.child; - while (child !== null) { - setCurrentFiber(child); - commitMutationEffectsOnFiber(child, root); - child = child.sibling; + function commitHookPassiveUnmountEffects( + finishedWork, + nearestMountedAncestor, + hookFlags + ) { + if (shouldProfile(finishedWork)) { + startPassiveEffectTimer(); + commitHookEffectListUnmount( + hookFlags, + finishedWork, + nearestMountedAncestor + ); + recordPassiveEffectDuration(finishedWork); + } else { + commitHookEffectListUnmount( + hookFlags, + finishedWork, + nearestMountedAncestor + ); + } } - } - - setCurrentFiber(prevDebugFiber); -} -function commitMutationEffectsOnFiber(finishedWork, root, lanes) { - var current = finishedWork.alternate; - var flags = finishedWork.flags; // The effect flag should be checked *after* we refine the type of fiber, - // because the fiber tag is more specific. An exception is any flag related - // to reconciliation, because those can be set on all fiber types. - - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case MemoComponent: - case SimpleMemoComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - - if (flags & Update) { - try { - commitHookEffectListUnmount( - Insertion | HasEffect, - finishedWork, - finishedWork.return - ); - commitHookEffectListMount(Insertion | HasEffect, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } // Layout effects are destroyed during the mutation phase so that all - // destroy functions for all fibers are called before any create functions. - // This prevents sibling component effects from interfering with each other, - // e.g. a destroy function in one component should never override a ref set - // by a create function in another component during the same commit. + function recursivelyTraversePassiveUnmountEffects(parentFiber) { + // Deletions effects can be scheduled on any fiber type. They need to happen + // before the children effects have fired. + var deletions = parentFiber.deletions; - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - commitHookEffectListUnmount( - Layout | HasEffect, - finishedWork, - finishedWork.return - ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + if ((parentFiber.flags & ChildDeletion) !== NoFlags$1) { + if (deletions !== null) { + for (var i = 0; i < deletions.length; i++) { + var childToDelete = deletions[i]; // TODO: Convert this to use recursion - recordLayoutEffectDuration(finishedWork); - } else { - try { - commitHookEffectListUnmount( - Layout | HasEffect, - finishedWork, - finishedWork.return + nextEffect = childToDelete; + commitPassiveUnmountEffectsInsideOfDeletedTree_begin( + childToDelete, + parentFiber ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); } } - } - - return; - } - - case ClassComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - if (flags & Ref) { - if (current !== null) { - safelyDetachRef(current, current.return); - } + detachAlternateSiblings(parentFiber); } - if (flags & Callback && offscreenSubtreeIsHidden) { - var updateQueue = finishedWork.updateQueue; + var prevDebugFiber = getCurrentFiber(); // TODO: Split PassiveMask into separate masks for mount and unmount? - if (updateQueue !== null) { - deferHiddenCallbacks(updateQueue); + if (parentFiber.subtreeFlags & PassiveMask) { + var child = parentFiber.child; + + while (child !== null) { + setCurrentFiber(child); + commitPassiveUnmountOnFiber(child); + child = child.sibling; } } - return; + setCurrentFiber(prevDebugFiber); } - case HostHoistable: - - case HostSingleton: + function commitPassiveUnmountOnFiber(finishedWork) { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + recursivelyTraversePassiveUnmountEffects(finishedWork); - case HostComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + if (finishedWork.flags & Passive$1) { + commitHookPassiveUnmountEffects( + finishedWork, + finishedWork.return, + Passive | HasEffect + ); + } - if (flags & Ref) { - if (current !== null) { - safelyDetachRef(current, current.return); + break; } - } - { - // TODO: ContentReset gets cleared by the children during the commit - // phase. This is a refactor hazard because it means we must read - // flags the flags after `commitReconciliationEffects` has already run; - // the order matters. We should refactor so that ContentReset does not - // rely on mutating the flag during commit. Like by setting a flag - // during the render phase instead. - if (finishedWork.flags & ContentReset) { + case OffscreenComponent: { var instance = finishedWork.stateNode; + var nextState = finishedWork.memoizedState; + var isHidden = nextState !== null; - try { - resetTextContent(instance); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + if ( + isHidden && + instance._visibility & OffscreenPassiveEffectsConnected && // For backwards compatibility, don't unmount when a tree suspends. In + // the future we may change this to unmount after a delay. + (finishedWork.return === null || + finishedWork.return.tag !== SuspenseComponent) + ) { + // The effects are currently connected. Disconnect them. + // TODO: Add option or heuristic to delay before disconnecting the + // effects. Then if the tree reappears before the delay has elapsed, we + // can skip toggling the effects entirely. + instance._visibility &= ~OffscreenPassiveEffectsConnected; + recursivelyTraverseDisconnectPassiveEffects(finishedWork); + } else { + recursivelyTraversePassiveUnmountEffects(finishedWork); } - } - if (flags & Update) { - var _instance2 = finishedWork.stateNode; + break; + } - if (_instance2 != null) { - // Commit the work prepared earlier. - var newProps = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps - // as the newProps. The updatePayload will contain the real change in - // this case. + default: { + recursivelyTraversePassiveUnmountEffects(finishedWork); + break; + } + } + } - var oldProps = current !== null ? current.memoizedProps : newProps; - var type = finishedWork.type; // TODO: Type the updateQueue to be specific to host components. + function recursivelyTraverseDisconnectPassiveEffects(parentFiber) { + // Deletions effects can be scheduled on any fiber type. They need to happen + // before the children effects have fired. + var deletions = parentFiber.deletions; - var _updatePayload = finishedWork.updateQueue; - finishedWork.updateQueue = null; + if ((parentFiber.flags & ChildDeletion) !== NoFlags$1) { + if (deletions !== null) { + for (var i = 0; i < deletions.length; i++) { + var childToDelete = deletions[i]; // TODO: Convert this to use recursion - try { - commitUpdate( - _instance2, - _updatePayload, - type, - oldProps, - newProps, - finishedWork - ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + nextEffect = childToDelete; + commitPassiveUnmountEffectsInsideOfDeletedTree_begin( + childToDelete, + parentFiber + ); } } + + detachAlternateSiblings(parentFiber); } - return; - } + var prevDebugFiber = getCurrentFiber(); // TODO: Check PassiveStatic flag - case HostText: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + var child = parentFiber.child; - if (flags & Update) { - { - if (finishedWork.stateNode === null) { - throw new Error( - "This should have a text node initialized. This error is likely " + - "caused by a bug in React. Please file an issue." - ); - } + while (child !== null) { + setCurrentFiber(child); + disconnectPassiveEffect(child); + child = child.sibling; + } - var textInstance = finishedWork.stateNode; - var newText = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps - // as the newProps. The updatePayload will contain the real change in - // this case. + setCurrentFiber(prevDebugFiber); + } - var oldText = current !== null ? current.memoizedProps : newText; + function disconnectPassiveEffect(finishedWork) { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + // TODO: Check PassiveStatic flag + commitHookPassiveUnmountEffects( + finishedWork, + finishedWork.return, + Passive + ); // When disconnecting passive effects, we fire the effects in the same + // order as during a deletiong: parent before child - try { - commitTextUpdate(textInstance, oldText, newText); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + recursivelyTraverseDisconnectPassiveEffects(finishedWork); + break; } - } - return; - } + case OffscreenComponent: { + var instance = finishedWork.stateNode; - case HostRoot: { - { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - } + if (instance._visibility & OffscreenPassiveEffectsConnected) { + instance._visibility &= ~OffscreenPassiveEffectsConnected; + recursivelyTraverseDisconnectPassiveEffects(finishedWork); + } - return; - } + break; + } - case HostPortal: { - { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + default: { + recursivelyTraverseDisconnectPassiveEffects(finishedWork); + break; + } } - - return; } - case SuspenseComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); // TODO: We should mark a flag on the Suspense fiber itself, rather than - // relying on the Offscreen fiber having a flag also being marked. The - // reason is that this offscreen fiber might not be part of the work-in- - // progress tree! It could have been reused from a previous render. This - // doesn't lead to incorrect behavior because we don't rely on the flag - // check alone; we also compare the states explicitly below. But for - // modeling purposes, we _should_ be able to rely on the flag check alone. - // So this is a bit fragile. - // - // Also, all this logic could/should move to the passive phase so it - // doesn't block paint. - - var offscreenFiber = finishedWork.child; + function commitPassiveUnmountEffectsInsideOfDeletedTree_begin( + deletedSubtreeRoot, + nearestMountedAncestor + ) { + while (nextEffect !== null) { + var fiber = nextEffect; // Deletion effects fire in parent -> child order + // TODO: Check if fiber has a PassiveStatic flag - if (offscreenFiber.flags & Visibility) { - // Throttle the appearance and disappearance of Suspense fallbacks. - var isShowingFallback = finishedWork.memoizedState !== null; - var wasShowingFallback = - current !== null && current.memoizedState !== null; + setCurrentFiber(fiber); + commitPassiveUnmountInsideDeletedTreeOnFiber( + fiber, + nearestMountedAncestor + ); + resetCurrentFiber(); + var child = fiber.child; // TODO: Only traverse subtree if it has a PassiveStatic flag. - if (alwaysThrottleRetries) { - if (isShowingFallback !== wasShowingFallback) { - // A fallback is either appearing or disappearing. - markCommitTimeOfFallback(); - } + if (child !== null) { + child.return = fiber; + nextEffect = child; } else { - if (isShowingFallback && !wasShowingFallback) { - // Old behavior. Only mark when a fallback appears, not when - // it disappears. - markCommitTimeOfFallback(); - } + commitPassiveUnmountEffectsInsideOfDeletedTree_complete( + deletedSubtreeRoot + ); } } + } - if (flags & Update) { - try { - commitSuspenseCallback(finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + function commitPassiveUnmountEffectsInsideOfDeletedTree_complete( + deletedSubtreeRoot + ) { + while (nextEffect !== null) { + var fiber = nextEffect; + var sibling = fiber.sibling; + var returnFiber = fiber.return; // Recursively traverse the entire deleted tree and clean up fiber fields. + // This is more aggressive than ideal, and the long term goal is to only + // have to detach the deleted tree at the root. - var retryQueue = finishedWork.updateQueue; + detachFiberAfterEffects(fiber); - if (retryQueue !== null) { - finishedWork.updateQueue = null; - attachSuspenseRetryListeners(finishedWork, retryQueue); + if (fiber === deletedSubtreeRoot) { + nextEffect = null; + return; } - } - - return; - } - case OffscreenComponent: { - if (flags & Ref) { - if (current !== null) { - safelyDetachRef(current, current.return); + if (sibling !== null) { + sibling.return = returnFiber; + nextEffect = sibling; + return; } - } - var newState = finishedWork.memoizedState; - var isHidden = newState !== null; - var wasHidden = current !== null && current.memoizedState !== null; - - if (finishedWork.mode & ConcurrentMode) { - // Before committing the children, track on the stack whether this - // offscreen subtree was already hidden, so that we don't unmount the - // effects again. - var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden; - var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; - offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden || isHidden; - offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden || wasHidden; - recursivelyTraverseMutationEffects(root, finishedWork); - offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; - offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; - } else { - recursivelyTraverseMutationEffects(root, finishedWork); + nextEffect = returnFiber; } + } - commitReconciliationEffects(finishedWork); - var offscreenInstance = finishedWork.stateNode; // TODO: Add explicit effect flag to set _current. - - offscreenInstance._current = finishedWork; // Offscreen stores pending changes to visibility in `_pendingVisibility`. This is - // to support batching of `attach` and `detach` calls. + function commitPassiveUnmountInsideDeletedTreeOnFiber( + current, + nearestMountedAncestor + ) { + switch (current.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + commitHookPassiveUnmountEffects( + current, + nearestMountedAncestor, + Passive + ); + break; + } + // TODO: run passive unmount effects when unmounting a root. + // Because passive unmount effects are not currently run, + // the cache instance owned by the root will never be freed. + // When effects are run, the cache should be freed here: + // case HostRoot: { + // if (enableCache) { + // const cache = current.memoizedState.cache; + // releaseCache(cache); + // } + // break; + // } + + case LegacyHiddenComponent: + case OffscreenComponent: { + { + if ( + current.memoizedState !== null && + current.memoizedState.cachePool !== null + ) { + var cache = current.memoizedState.cachePool.pool; // Retain/release the cache used for pending (suspended) nodes. + // Note that this is only reached in the non-suspended/visible case: + // when the content is suspended/hidden, the retain/release occurs + // via the parent Suspense component (see case above). - offscreenInstance._visibility &= ~OffscreenDetached; - offscreenInstance._visibility |= - offscreenInstance._pendingVisibility & OffscreenDetached; + if (cache != null) { + retainCache(cache); + } + } + } - if (flags & Visibility) { - // Track the current state on the Offscreen instance so we can - // read it during an event - if (isHidden) { - offscreenInstance._visibility &= ~OffscreenVisible; - } else { - offscreenInstance._visibility |= OffscreenVisible; + break; } - if (isHidden) { - var isUpdate = current !== null; - var wasHiddenByAncestorOffscreen = - offscreenSubtreeIsHidden || offscreenSubtreeWasHidden; // Only trigger disapper layout effects if: - // - This is an update, not first mount. - // - This Offscreen was not hidden before. - // - Ancestor Offscreen was not hidden in previous commit. + case SuspenseComponent: { + if (enableTransitionTracing) { + // We need to mark this fiber's parents as deleted + var offscreenFiber = current.child; + var instance = offscreenFiber.stateNode; + var transitions = instance._transitions; + + if (transitions !== null) { + var abortReason = { + reason: "suspense", + name: current.memoizedProps.unstable_name || null + }; + + if ( + current.memoizedState === null || + current.memoizedState.dehydrated === null + ) { + abortParentMarkerTransitionsForDeletedFiber( + offscreenFiber, + abortReason, + transitions, + instance, + true + ); - if (isUpdate && !wasHidden && !wasHiddenByAncestorOffscreen) { - if ((finishedWork.mode & ConcurrentMode) !== NoMode) { - // Disappear the layout effects of all the children - recursivelyTraverseDisappearLayoutEffects(finishedWork); + if (nearestMountedAncestor !== null) { + abortParentMarkerTransitionsForDeletedFiber( + nearestMountedAncestor, + abortReason, + transitions, + instance, + false + ); + } + } } } - } // Offscreen with manual mode manages visibility manually. - if (!isOffscreenManual(finishedWork)) { - // TODO: This needs to run whenever there's an insertion or update - // inside a hidden Offscreen tree. - hideOrUnhideAllChildren(finishedWork, isHidden); + break; } - } // TODO: Move to passive phase - - if (flags & Update) { - var offscreenQueue = finishedWork.updateQueue; - - if (offscreenQueue !== null) { - var _retryQueue = offscreenQueue.retryQueue; - if (_retryQueue !== null) { - offscreenQueue.retryQueue = null; - attachSuspenseRetryListeners(finishedWork, _retryQueue); + case CacheComponent: { + { + var _cache = current.memoizedState.cache; + releaseCache(_cache); } + + break; } - } - return; - } + case TracingMarkerComponent: { + if (enableTransitionTracing) { + // We need to mark this fiber's parents as deleted + var _instance5 = current.stateNode; + var _transitions = _instance5.transitions; - case SuspenseListComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + if (_transitions !== null) { + var _abortReason = { + reason: "marker", + name: current.memoizedProps.name + }; + abortParentMarkerTransitionsForDeletedFiber( + current, + _abortReason, + _transitions, + null, + true + ); - if (flags & Update) { - var _retryQueue2 = finishedWork.updateQueue; + if (nearestMountedAncestor !== null) { + abortParentMarkerTransitionsForDeletedFiber( + nearestMountedAncestor, + _abortReason, + _transitions, + null, + false + ); + } + } + } - if (_retryQueue2 !== null) { - finishedWork.updateQueue = null; - attachSuspenseRetryListeners(finishedWork, _retryQueue2); + break; } } - - return; } - case ScopeComponent: { + function invokeLayoutEffectMountInDEV(fiber) { { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); // TODO: This is a temporary solution that allowed us to transition away - // from React Flare on www. + // We don't need to re-check StrictEffectsMode here. + // This function is only called if that check has already passed. + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + try { + commitHookEffectListMount(Layout | HasEffect, fiber); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } - if (flags & Ref) { - if (current !== null) { - safelyDetachRef(finishedWork, finishedWork.return); + break; } - safelyAttachRef(finishedWork, finishedWork.return); - } + case ClassComponent: { + var instance = fiber.stateNode; + + if (typeof instance.componentDidMount === "function") { + try { + instance.componentDidMount(); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } + } - if (flags & Update) { - prepareScopeUpdate(); + break; + } } } - - return; - } - - default: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - return; } - } -} -function commitReconciliationEffects(finishedWork) { - // Placement effects (insertions, reorders) can be scheduled on any fiber - // type. They needs to happen after the children effects have fired, but - // before the effects on this fiber have fired. - var flags = finishedWork.flags; - - if (flags & Placement) { - try { - commitPlacement(finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } // Clear the "placement" from effect tag so that we know that this is - // inserted, before any life-cycles like componentDidMount gets called. - // TODO: findDOMNode doesn't rely on this any more but isMounted does - // and isMounted is deprecated anyway so we should be able to kill this. - - finishedWork.flags &= ~Placement; - } - - if (flags & Hydrating) { - finishedWork.flags &= ~Hydrating; - } -} + function invokePassiveEffectMountInDEV(fiber) { + { + // We don't need to re-check StrictEffectsMode here. + // This function is only called if that check has already passed. + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + try { + commitHookEffectListMount(Passive | HasEffect, fiber); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } -function commitLayoutEffects(finishedWork, root, committedLanes) { - inProgressLanes = committedLanes; - inProgressRoot = root; - var current = finishedWork.alternate; - commitLayoutEffectOnFiber(root, current, finishedWork); - inProgressLanes = null; - inProgressRoot = null; -} + break; + } + } + } + } -function recursivelyTraverseLayoutEffects(root, parentFiber, lanes) { - var prevDebugFiber = getCurrentFiber(); + function invokeLayoutEffectUnmountInDEV(fiber) { + { + // We don't need to re-check StrictEffectsMode here. + // This function is only called if that check has already passed. + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + try { + commitHookEffectListUnmount( + Layout | HasEffect, + fiber, + fiber.return + ); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } - if (parentFiber.subtreeFlags & LayoutMask) { - var child = parentFiber.child; + break; + } - while (child !== null) { - setCurrentFiber(child); - var current = child.alternate; - commitLayoutEffectOnFiber(root, current, child); - child = child.sibling; - } - } + case ClassComponent: { + var instance = fiber.stateNode; - setCurrentFiber(prevDebugFiber); -} + if (typeof instance.componentWillUnmount === "function") { + safelyCallComponentWillUnmount(fiber, fiber.return, instance); + } -function disappearLayoutEffects(finishedWork) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case MemoComponent: - case SimpleMemoComponent: { - // TODO (Offscreen) Check: flags & LayoutStatic - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - commitHookEffectListUnmount( - Layout, - finishedWork, - finishedWork.return - ); - } finally { - recordLayoutEffectDuration(finishedWork); + break; + } } - } else { - commitHookEffectListUnmount(Layout, finishedWork, finishedWork.return); } - - recursivelyTraverseDisappearLayoutEffects(finishedWork); - break; } - case ClassComponent: { - // TODO (Offscreen) Check: flags & RefStatic - safelyDetachRef(finishedWork, finishedWork.return); - var instance = finishedWork.stateNode; - - if (typeof instance.componentWillUnmount === "function") { - safelyCallComponentWillUnmount( - finishedWork, - finishedWork.return, - instance - ); + function invokePassiveEffectUnmountInDEV(fiber) { + { + // We don't need to re-check StrictEffectsMode here. + // This function is only called if that check has already passed. + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + try { + commitHookEffectListUnmount( + Passive | HasEffect, + fiber, + fiber.return + ); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } + } + } } - - recursivelyTraverseDisappearLayoutEffects(finishedWork); - break; } - case HostHoistable: - case HostSingleton: - case HostComponent: { - // TODO (Offscreen) Check: flags & RefStatic - safelyDetachRef(finishedWork, finishedWork.return); - recursivelyTraverseDisappearLayoutEffects(finishedWork); - break; + function getCacheSignal() { + var cache = readContext(CacheContext); + return cache.controller.signal; } - case OffscreenComponent: { - // TODO (Offscreen) Check: flags & RefStatic - safelyDetachRef(finishedWork, finishedWork.return); - var isHidden = finishedWork.memoizedState !== null; + function getCacheForType(resourceType) { + var cache = readContext(CacheContext); + var cacheForType = cache.data.get(resourceType); - if (isHidden); - else { - recursivelyTraverseDisappearLayoutEffects(finishedWork); + if (cacheForType === undefined) { + cacheForType = resourceType(); + cache.data.set(resourceType, cacheForType); } - break; + return cacheForType; } - default: { - recursivelyTraverseDisappearLayoutEffects(finishedWork); - break; - } - } -} - -function recursivelyTraverseDisappearLayoutEffects(parentFiber) { - // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) - var child = parentFiber.child; - - while (child !== null) { - disappearLayoutEffects(child); - child = child.sibling; - } -} - -function reappearLayoutEffects( - finishedRoot, - current, - finishedWork, // This function visits both newly finished work and nodes that were re-used - // from a previously committed tree. We cannot check non-static flags if the - // node was reused. - includeWorkInProgressEffects -) { - // Turn on layout effects in a tree that previously disappeared. - var flags = finishedWork.flags; - - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); // TODO: Check flags & LayoutStatic + var DefaultCacheDispatcher = { + getCacheSignal: getCacheSignal, + getCacheForType: getCacheForType + }; - commitHookLayoutEffects(finishedWork, Layout); - break; + if (typeof Symbol === "function" && Symbol.for) { + var symbolFor = Symbol.for; + symbolFor("selector.component"); + symbolFor("selector.has_pseudo_class"); + symbolFor("selector.role"); + symbolFor("selector.test_id"); + symbolFor("selector.text"); } - case ClassComponent: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); // TODO: Check for LayoutStatic flag - - var instance = finishedWork.stateNode; + var ReactCurrentActQueue$1 = ReactSharedInternals.ReactCurrentActQueue; + function isLegacyActEnvironment(fiber) { + { + // Legacy mode. We preserve the behavior of React 17's act. It assumes an + // act environment whenever `jest` is defined, but you can still turn off + // spurious warnings by setting IS_REACT_ACT_ENVIRONMENT explicitly + // to false. + // $FlowFixMe[cannot-resolve-name] Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global + typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" // $FlowFixMe[cannot-resolve-name] + ? IS_REACT_ACT_ENVIRONMENT + : undefined; // $FlowFixMe[cannot-resolve-name] - Flow doesn't know about jest + return warnsIfNotActing; + } + } + function isConcurrentActEnvironment() { + { + var isReactActEnvironmentGlobal = // $FlowFixMe[cannot-resolve-name] Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global + typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" // $FlowFixMe[cannot-resolve-name] + ? IS_REACT_ACT_ENVIRONMENT + : undefined; - if (typeof instance.componentDidMount === "function") { - try { - instance.componentDidMount(); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + if ( + !isReactActEnvironmentGlobal && + ReactCurrentActQueue$1.current !== null + ) { + // TODO: Include link to relevant documentation page. + error( + "The current testing environment is not configured to support " + + "act(...)" + ); } - } // Commit any callbacks that would have fired while the component - // was hidden. - var updateQueue = finishedWork.updateQueue; + return isReactActEnvironmentGlobal; + } + } + + var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; + var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, + ReactCurrentCache = ReactSharedInternals.ReactCurrentCache, + ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner, + ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig, + ReactCurrentActQueue = ReactSharedInternals.ReactCurrentActQueue; + var NoContext = + /* */ + 0; + var BatchedContext = + /* */ + 1; + var RenderContext = + /* */ + 2; + var CommitContext = + /* */ + 4; + var RootInProgress = 0; + var RootFatalErrored = 1; + var RootErrored = 2; + var RootSuspended = 3; + var RootSuspendedWithDelay = 4; + var RootCompleted = 5; + var RootDidNotComplete = 6; // Describes where we are in the React execution stack + + var executionContext = NoContext; // The root we're working on + + var workInProgressRoot = null; // The fiber we're working on + + var workInProgress = null; // The lanes we're rendering + + var workInProgressRootRenderLanes = NoLanes; + var NotSuspended = 0; + var SuspendedOnError = 1; + var SuspendedOnData = 2; + var SuspendedOnImmediate = 3; + var SuspendedOnInstance = 4; + var SuspendedOnInstanceAndReadyToContinue = 5; + var SuspendedOnDeprecatedThrowPromise = 6; + var SuspendedAndReadyToContinue = 7; + var SuspendedOnHydration = 8; // When this is true, the work-in-progress fiber just suspended (or errored) and + // we've yet to unwind the stack. In some cases, we may yield to the main thread + // after this happens. If the fiber is pinged before we resume, we can retry + // immediately instead of unwinding the stack. + + var workInProgressSuspendedReason = NotSuspended; + var workInProgressThrownValue = null; // Whether a ping listener was attached during this render. This is slightly + // different that whether something suspended, because we don't add multiple + // listeners to a promise we've already seen (per root and lane). + + var workInProgressRootDidAttachPingListener = false; // A contextual version of workInProgressRootRenderLanes. It is a superset of + // the lanes that we started working on at the root. When we enter a subtree + // that is currently hidden, we add the lanes that would have committed if + // the hidden tree hadn't been deferred. This is modified by the + // HiddenContext module. + // + // Most things in the work loop should deal with workInProgressRootRenderLanes. + // Most things in begin/complete phases should deal with entangledRenderLanes. - if (updateQueue !== null) { - commitHiddenCallbacks(updateQueue, instance); - } // If this is newly finished work, check for setState callbacks - - if (includeWorkInProgressEffects && flags & Callback) { - commitClassCallbacks(finishedWork); - } // TODO: Check flags & RefStatic - - safelyAttachRef(finishedWork, finishedWork.return); - break; - } - // Unlike commitLayoutEffectsOnFiber, we don't need to handle HostRoot - // because this function only visits nodes that are inside an - // Offscreen fiber. - // case HostRoot: { - // ... - // } - - case HostHoistable: - case HostSingleton: - case HostComponent: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); // Renderers may schedule work to be done after host components are mounted - // (eg DOM renderer may schedule auto-focus for inputs and form controls). - // These effects should only be committed when components are first mounted, - // aka when there is no current/alternate. + var entangledRenderLanes = NoLanes; // Whether to root completed, errored, suspended, etc. - if (includeWorkInProgressEffects && current === null && flags & Update) { - commitHostComponentMount(finishedWork); - } // TODO: Check flags & Ref + var workInProgressRootExitStatus = RootInProgress; // A fatal error, if one is thrown - safelyAttachRef(finishedWork, finishedWork.return); - break; - } + var workInProgressRootFatalError = null; // The work left over by components that were visited during this render. Only + // includes unprocessed updates, not work in bailed out children. - case Profiler: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); // TODO: Figure out how Profiler updates should work with Offscreen + var workInProgressRootSkippedLanes = NoLanes; // Lanes that were updated (in an interleaved event) during this render. - if (includeWorkInProgressEffects && flags & Update) { - commitProfilerUpdate(finishedWork, current); - } + var workInProgressRootInterleavedUpdatedLanes = NoLanes; // Lanes that were updated during the render phase (*not* an interleaved event). - break; - } + var workInProgressRootPingedLanes = NoLanes; // If this lane scheduled deferred work, this is the lane of the deferred task. - case SuspenseComponent: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); // TODO: Figure out how Suspense hydration callbacks should work + var workInProgressDeferredLane = NoLane; // Errors that are thrown during the render phase. - break; - } + var workInProgressRootConcurrentErrors = null; // These are errors that we recovered from without surfacing them to the UI. + // We will log them once the tree commits. - case OffscreenComponent: { - var offscreenState = finishedWork.memoizedState; - var isHidden = offscreenState !== null; + var workInProgressRootRecoverableErrors = null; // The most recent time we either committed a fallback, or when a fallback was + // filled in with the resolved UI. This lets us throttle the appearance of new + // content as it streams in, to minimize jank. + // TODO: Think of a better name for this variable? - if (isHidden); - else { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); - } // TODO: Check flags & Ref + var globalMostRecentFallbackTime = 0; + var FALLBACK_THROTTLE_MS = 300; // The absolute time for when we should start giving up on rendering + // more and prefer CPU suspense heuristics instead. - safelyAttachRef(finishedWork, finishedWork.return); - break; - } + var workInProgressRootRenderTargetTime = Infinity; // How long a render is supposed to take before we start following CPU + // suspense heuristics and opt out of rendering more content. - default: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); - break; + var RENDER_TIMEOUT_MS = 500; + var workInProgressTransitions = null; + function getWorkInProgressTransitions() { + return workInProgressTransitions; } - } -} - -function recursivelyTraverseReappearLayoutEffects( - finishedRoot, - parentFiber, - includeWorkInProgressEffects -) { - // This function visits both newly finished work and nodes that were re-used - // from a previously committed tree. We cannot check non-static flags if the - // node was reused. - var childShouldIncludeWorkInProgressEffects = - includeWorkInProgressEffects && - (parentFiber.subtreeFlags & LayoutMask) !== NoFlags$1; // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) - - var prevDebugFiber = getCurrentFiber(); - var child = parentFiber.child; - - while (child !== null) { - var current = child.alternate; - reappearLayoutEffects( - finishedRoot, - current, - child, - childShouldIncludeWorkInProgressEffects - ); - child = child.sibling; - } - - setCurrentFiber(prevDebugFiber); -} - -function commitHookPassiveMountEffects(finishedWork, hookFlags) { - if (shouldProfile(finishedWork)) { - startPassiveEffectTimer(); + var currentPendingTransitionCallbacks = null; + var currentEndTime = null; + function addTransitionStartCallbackToPendingTransition(transition) { + if (enableTransitionTracing) { + if (currentPendingTransitionCallbacks === null) { + currentPendingTransitionCallbacks = { + transitionStart: [], + transitionProgress: null, + transitionComplete: null, + markerProgress: null, + markerIncomplete: null, + markerComplete: null + }; + } - try { - commitHookEffectListMount(hookFlags, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + if (currentPendingTransitionCallbacks.transitionStart === null) { + currentPendingTransitionCallbacks.transitionStart = []; + } - recordPassiveEffectDuration(finishedWork); - } else { - try { - commitHookEffectListMount(hookFlags, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + currentPendingTransitionCallbacks.transitionStart.push(transition); + } } - } -} - -function commitOffscreenPassiveMountEffects(current, finishedWork, instance) { - { - var previousCache = null; - - if ( - current !== null && - current.memoizedState !== null && - current.memoizedState.cachePool !== null + function addMarkerProgressCallbackToPendingTransition( + markerName, + transitions, + pendingBoundaries ) { - previousCache = current.memoizedState.cachePool.pool; - } + if (enableTransitionTracing) { + if (currentPendingTransitionCallbacks === null) { + currentPendingTransitionCallbacks = { + transitionStart: null, + transitionProgress: null, + transitionComplete: null, + markerProgress: new Map(), + markerIncomplete: null, + markerComplete: null + }; + } - var nextCache = null; + if (currentPendingTransitionCallbacks.markerProgress === null) { + currentPendingTransitionCallbacks.markerProgress = new Map(); + } - if ( - finishedWork.memoizedState !== null && - finishedWork.memoizedState.cachePool !== null + currentPendingTransitionCallbacks.markerProgress.set(markerName, { + pendingBoundaries: pendingBoundaries, + transitions: transitions + }); + } + } + function addMarkerIncompleteCallbackToPendingTransition( + markerName, + transitions, + aborts ) { - nextCache = finishedWork.memoizedState.cachePool.pool; - } // Retain/release the cache used for pending (suspended) nodes. - // Note that this is only reached in the non-suspended/visible case: - // when the content is suspended/hidden, the retain/release occurs - // via the parent Suspense component (see case above). + if (enableTransitionTracing) { + if (currentPendingTransitionCallbacks === null) { + currentPendingTransitionCallbacks = { + transitionStart: null, + transitionProgress: null, + transitionComplete: null, + markerProgress: null, + markerIncomplete: new Map(), + markerComplete: null + }; + } - if (nextCache !== previousCache) { - if (nextCache != null) { - retainCache(nextCache); - } + if (currentPendingTransitionCallbacks.markerIncomplete === null) { + currentPendingTransitionCallbacks.markerIncomplete = new Map(); + } - if (previousCache != null) { - releaseCache(previousCache); + currentPendingTransitionCallbacks.markerIncomplete.set(markerName, { + transitions: transitions, + aborts: aborts + }); } } - } - - if (enableTransitionTracing) { - // TODO: Pre-rendering should not be counted as part of a transition. We - // may add separate logs for pre-rendering, but it's not part of the - // primary metrics. - var offscreenState = finishedWork.memoizedState; - var queue = finishedWork.updateQueue; - var isHidden = offscreenState !== null; - - if (queue !== null) { - if (isHidden) { - var transitions = queue.transitions; - - if (transitions !== null) { - transitions.forEach(function (transition) { - // Add all the transitions saved in the update queue during - // the render phase (ie the transitions associated with this boundary) - // into the transitions set. - if (instance._transitions === null) { - instance._transitions = new Set(); - } - - instance._transitions.add(transition); - }); + function addMarkerCompleteCallbackToPendingTransition( + markerName, + transitions + ) { + if (enableTransitionTracing) { + if (currentPendingTransitionCallbacks === null) { + currentPendingTransitionCallbacks = { + transitionStart: null, + transitionProgress: null, + transitionComplete: null, + markerProgress: null, + markerIncomplete: null, + markerComplete: new Map() + }; } - var markerInstances = queue.markerInstances; - - if (markerInstances !== null) { - markerInstances.forEach(function (markerInstance) { - var markerTransitions = markerInstance.transitions; // There should only be a few tracing marker transitions because - // they should be only associated with the transition that - // caused them - - if (markerTransitions !== null) { - markerTransitions.forEach(function (transition) { - if (instance._transitions === null) { - instance._transitions = new Set(); - } else if (instance._transitions.has(transition)) { - if (markerInstance.pendingBoundaries === null) { - markerInstance.pendingBoundaries = new Map(); - } - - if (instance._pendingMarkers === null) { - instance._pendingMarkers = new Set(); - } - - instance._pendingMarkers.add(markerInstance); - } - }); - } - }); + if (currentPendingTransitionCallbacks.markerComplete === null) { + currentPendingTransitionCallbacks.markerComplete = new Map(); } - } - finishedWork.updateQueue = null; + currentPendingTransitionCallbacks.markerComplete.set( + markerName, + transitions + ); + } } + function addTransitionProgressCallbackToPendingTransition( + transition, + boundaries + ) { + if (enableTransitionTracing) { + if (currentPendingTransitionCallbacks === null) { + currentPendingTransitionCallbacks = { + transitionStart: null, + transitionProgress: new Map(), + transitionComplete: null, + markerProgress: null, + markerIncomplete: null, + markerComplete: null + }; + } - commitTransitionProgress(finishedWork); // TODO: Refactor this into an if/else branch + if (currentPendingTransitionCallbacks.transitionProgress === null) { + currentPendingTransitionCallbacks.transitionProgress = new Map(); + } - if (!isHidden) { - instance._transitions = null; - instance._pendingMarkers = null; + currentPendingTransitionCallbacks.transitionProgress.set( + transition, + boundaries + ); + } } - } -} + function addTransitionCompleteCallbackToPendingTransition(transition) { + if (enableTransitionTracing) { + if (currentPendingTransitionCallbacks === null) { + currentPendingTransitionCallbacks = { + transitionStart: null, + transitionProgress: null, + transitionComplete: [], + markerProgress: null, + markerIncomplete: null, + markerComplete: null + }; + } -function commitCachePassiveMountEffect(current, finishedWork) { - { - var previousCache = null; + if (currentPendingTransitionCallbacks.transitionComplete === null) { + currentPendingTransitionCallbacks.transitionComplete = []; + } - if (finishedWork.alternate !== null) { - previousCache = finishedWork.alternate.memoizedState.cache; + currentPendingTransitionCallbacks.transitionComplete.push(transition); + } } - var nextCache = finishedWork.memoizedState.cache; // Retain/release the cache. In theory the cache component - // could be "borrowing" a cache instance owned by some parent, - // in which case we could avoid retaining/releasing. But it - // is non-trivial to determine when that is the case, so we - // always retain/release. - - if (nextCache !== previousCache) { - retainCache(nextCache); - - if (previousCache != null) { - releaseCache(previousCache); - } + function resetRenderTimer() { + workInProgressRootRenderTargetTime = now$1() + RENDER_TIMEOUT_MS; } - } -} -function commitTracingMarkerPassiveMountEffect(finishedWork) { - // Get the transitions that were initiatized during the render - // and add a start transition callback for each of them - // We will only call this on initial mount of the tracing marker - // only if there are no suspense children - var instance = finishedWork.stateNode; - - if (instance.transitions !== null && instance.pendingBoundaries === null) { - addMarkerCompleteCallbackToPendingTransition( - finishedWork.memoizedProps.name, - instance.transitions - ); - instance.transitions = null; - instance.pendingBoundaries = null; - instance.aborts = null; - instance.name = null; - } -} + function getRenderTargetTime() { + return workInProgressRootRenderTargetTime; + } + var hasUncaughtError = false; + var firstUncaughtError = null; + var legacyErrorBoundariesThatAlreadyFailed = null; // Only used when enableProfilerNestedUpdateScheduledHook is true; + // to track which root is currently committing layout effects. -function commitPassiveMountEffects( - root, - finishedWork, - committedLanes, - committedTransitions -) { - setCurrentFiber(finishedWork); - commitPassiveMountOnFiber( - root, - finishedWork, - committedLanes, - committedTransitions - ); - resetCurrentFiber(); -} + var rootCommittingMutationOrLayoutEffects = null; + var rootDoesHavePassiveEffects = false; + var rootWithPendingPassiveEffects = null; + var pendingPassiveEffectsLanes = NoLanes; + var pendingPassiveProfilerEffects = []; + var pendingPassiveEffectsRemainingLanes = NoLanes; + var pendingPassiveTransitions = null; // Use these to prevent an infinite loop of nested updates -function recursivelyTraversePassiveMountEffects( - root, - parentFiber, - committedLanes, - committedTransitions -) { - var prevDebugFiber = getCurrentFiber(); + var NESTED_UPDATE_LIMIT = 50; + var nestedUpdateCount = 0; + var rootWithNestedUpdates = null; + var isFlushingPassiveEffects = false; + var didScheduleUpdateDuringPassiveEffects = false; + var NESTED_PASSIVE_UPDATE_LIMIT = 50; + var nestedPassiveUpdateCount = 0; + var rootWithPassiveNestedUpdates = null; + var isRunningInsertionEffect = false; + function getWorkInProgressRoot() { + return workInProgressRoot; + } + function getWorkInProgressRootRenderLanes() { + return workInProgressRootRenderLanes; + } + function isWorkLoopSuspendedOnData() { + return workInProgressSuspendedReason === SuspendedOnData; + } + function requestUpdateLane(fiber) { + // Special cases + var mode = fiber.mode; - if (parentFiber.subtreeFlags & PassiveMask) { - var child = parentFiber.child; + if ((mode & ConcurrentMode) === NoMode) { + return SyncLane; + } else if ( + (executionContext & RenderContext) !== NoContext && + workInProgressRootRenderLanes !== NoLanes + ) { + // This is a render phase update. These are not officially supported. The + // old behavior is to give this the same "thread" (lanes) as + // whatever is currently rendering. So if you call `setState` on a component + // that happens later in the same render, it will flush. Ideally, we want to + // remove the special case and treat them as if they came from an + // interleaved event. Regardless, this pattern is not officially supported. + // This behavior is only a fallback. The flag only exists until we can roll + // out the setState warning, since existing code might accidentally rely on + // the current behavior. + return pickArbitraryLane(workInProgressRootRenderLanes); + } + + var isTransition = requestCurrentTransition() !== NoTransition; + + if (isTransition) { + if (ReactCurrentBatchConfig.transition !== null) { + var transition = ReactCurrentBatchConfig.transition; + + if (!transition._updatedFibers) { + transition._updatedFibers = new Set(); + } - while (child !== null) { - setCurrentFiber(child); - commitPassiveMountOnFiber( - root, - child, - committedLanes, - committedTransitions - ); - child = child.sibling; - } - } + transition._updatedFibers.add(fiber); + } - setCurrentFiber(prevDebugFiber); -} + var actionScopeLane = peekEntangledActionLane(); + return actionScopeLane !== NoLane // We're inside an async action scope. Reuse the same lane. + ? actionScopeLane // We may or may not be inside an async action scope. If we are, this + : // is the first update in that scope. Either way, we need to get a + // fresh transition lane. + requestTransitionLane(); + } // Updates originating inside certain React methods, like flushSync, have + // their priority set by tracking it with a context variable. + // + // The opaque type returned by the host config is internally a lane, so we can + // use that directly. + // TODO: Move this type conversion to the event priority module. -function commitPassiveMountOnFiber( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions -) { - // When updating this function, also update reconnectPassiveEffects, which does - // most of the same things when an offscreen tree goes from hidden -> visible, - // or when toggling effects inside a hidden tree. - var flags = finishedWork.flags; - - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); + var updateLane = getCurrentUpdatePriority(); - if (flags & Passive$1) { - commitHookPassiveMountEffects(finishedWork, Passive | HasEffect); + if (updateLane !== NoLane) { + return updateLane; + } // This update originated outside React. Ask the host environment for an + // appropriate priority, based on the type of event. + // + // The opaque type returned by the host config is internally a lane, so we can + // use that directly. + // TODO: Move this type conversion to the event priority module. + + var eventLane = getCurrentEventPriority(); + return eventLane; + } + + function requestRetryLane(fiber) { + // This is a fork of `requestUpdateLane` designed specifically for Suspense + // "retries" — a special update that attempts to flip a Suspense boundary + // from its placeholder state to its primary/resolved state. + // Special cases + var mode = fiber.mode; + + if ((mode & ConcurrentMode) === NoMode) { + return SyncLane; + } + + return claimNextRetryLane(); + } + + function requestDeferredLane() { + if (workInProgressDeferredLane === NoLane) { + // If there are multiple useDeferredValue hooks in the same render, the + // tasks that they spawn should all be batched together, so they should all + // receive the same lane. + // Check the priority of the current render to decide the priority of the + // deferred task. + // OffscreenLane is used for prerendering, but we also use OffscreenLane + // for incremental hydration. It's given the lowest priority because the + // initial HTML is the same as the final UI. But useDeferredValue during + // hydration is an exception — we need to upgrade the UI to the final + // value. So if we're currently hydrating, we treat it like a transition. + var isPrerendering = + includesSomeLane(workInProgressRootRenderLanes, OffscreenLane) && + !getIsHydrating(); + + if (isPrerendering) { + // There's only one OffscreenLane, so if it contains deferred work, we + // should just reschedule using the same lane. + workInProgressDeferredLane = OffscreenLane; + } else { + // Everything else is spawned as a transition. + workInProgressDeferredLane = requestTransitionLane(); + } } - break; + return workInProgressDeferredLane; } + function scheduleUpdateOnFiber(root, fiber, lane) { + { + if (isRunningInsertionEffect) { + error("useInsertionEffect must not schedule updates."); + } + } - case HostRoot: { - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); + { + if (isFlushingPassiveEffects) { + didScheduleUpdateDuringPassiveEffects = true; + } + } // Check if the work loop is currently suspended and waiting for data to + // finish loading. - if (flags & Passive$1) { - { - var previousCache = null; + if ( + // Suspended render phase + (root === workInProgressRoot && + workInProgressSuspendedReason === SuspendedOnData) || // Suspended commit phase + root.cancelPendingCommit !== null + ) { + // The incoming update might unblock the current render. Interrupt the + // current attempt and restart from the top. + prepareFreshStack(root, NoLanes); + markRootSuspended( + root, + workInProgressRootRenderLanes, + workInProgressDeferredLane + ); + } // Mark that the root has a pending update. - if (finishedWork.alternate !== null) { - previousCache = finishedWork.alternate.memoizedState.cache; + markRootUpdated(root, lane); + + if ( + (executionContext & RenderContext) !== NoLanes && + root === workInProgressRoot + ) { + // This update was dispatched during the render phase. This is a mistake + // if the update originates from user space (with the exception of local + // hook updates, which are handled differently and don't reach this + // function), but there are some internal React features that use this as + // an implementation detail, like selective hydration. + warnAboutRenderPhaseUpdatesInDEV(fiber); // Track lanes that were updated during the render phase + } else { + // This is a normal update, scheduled from outside the render phase. For + // example, during an input event. + { + if (isDevToolsPresent) { + addFiberToLanesMap(root, fiber, lane); } + } - var nextCache = finishedWork.memoizedState.cache; // Retain/release the root cache. - // Note that on initial mount, previousCache and nextCache will be the same - // and this retain won't occur. To counter this, we instead retain the HostRoot's - // initial cache when creating the root itself (see createFiberRoot() in - // ReactFiberRoot.js). Subsequent updates that change the cache are reflected - // here, such that previous/next caches are retained correctly. + warnIfUpdatesNotWrappedWithActDEV(fiber); - if (nextCache !== previousCache) { - retainCache(nextCache); + if (enableProfilerNestedUpdateScheduledHook) { + if ( + (executionContext & CommitContext) !== NoContext && + root === rootCommittingMutationOrLayoutEffects + ) { + if (fiber.mode & ProfileMode) { + var current = fiber; + + while (current !== null) { + if (current.tag === Profiler) { + var _current$memoizedProp = current.memoizedProps, + id = _current$memoizedProp.id, + onNestedUpdateScheduled = + _current$memoizedProp.onNestedUpdateScheduled; + + if (typeof onNestedUpdateScheduled === "function") { + onNestedUpdateScheduled(id); + } + } - if (previousCache != null) { - releaseCache(previousCache); + current = current.return; + } } } } if (enableTransitionTracing) { - // Get the transitions that were initiatized during the render - // and add a start transition callback for each of them - var root = finishedWork.stateNode; - var incompleteTransitions = root.incompleteTransitions; // Initial render - - if (committedTransitions !== null) { - committedTransitions.forEach(function (transition) { - addTransitionStartCallbackToPendingTransition(transition); - }); - clearTransitionsForLanes(finishedRoot, committedLanes); + var transition = ReactCurrentBatchConfig.transition; + + if (transition !== null && transition.name != null) { + if (transition.startTime === -1) { + transition.startTime = now$1(); + } + + addTransitionToLanesMap(root, transition, lane); } + } - incompleteTransitions.forEach(function (markerInstance, transition) { - var pendingBoundaries = markerInstance.pendingBoundaries; + if (root === workInProgressRoot) { + // Received an update to a tree that's in the middle of rendering. Mark + // that there was an interleaved update work on this root. + if ((executionContext & RenderContext) === NoContext) { + workInProgressRootInterleavedUpdatedLanes = mergeLanes( + workInProgressRootInterleavedUpdatedLanes, + lane + ); + } - if (pendingBoundaries === null || pendingBoundaries.size === 0) { - if (markerInstance.aborts === null) { - addTransitionCompleteCallbackToPendingTransition(transition); - } + if (workInProgressRootExitStatus === RootSuspendedWithDelay) { + // The root already suspended with a delay, which means this render + // definitely won't finish. Since we have a new update, let's mark it as + // suspended now, right before marking the incoming update. This has the + // effect of interrupting the current render and switching to the update. + // TODO: Make sure this doesn't override pings that happen while we've + // already started rendering. + markRootSuspended( + root, + workInProgressRootRenderLanes, + workInProgressDeferredLane + ); + } + } - incompleteTransitions.delete(transition); - } - }); - clearTransitionsForLanes(finishedRoot, committedLanes); + ensureRootIsScheduled(root); + + if ( + lane === SyncLane && + executionContext === NoContext && + (fiber.mode & ConcurrentMode) === NoMode + ) { + if (ReactCurrentActQueue.isBatchingLegacy); + else { + // Flush the synchronous work now, unless we're already working or inside + // a batch. This is intentionally inside scheduleUpdateOnFiber instead of + // scheduleCallbackForFiber to preserve the ability to schedule a callback + // without immediately flushing it. We only do this for user-initiated + // updates, to preserve historical behavior of legacy mode. + resetRenderTimer(); + flushSyncWorkOnLegacyRootsOnly(); + } } } - - break; } + function isUnsafeClassRenderPhaseUpdate(fiber) { + // Check if this is a render phase update. Only called by class components, + // which special (deprecated) behavior for UNSAFE_componentWillReceive props. + return (executionContext & RenderContext) !== NoContext; + } // This is the entry point for every concurrent task, i.e. anything that + // goes through Scheduler. - case LegacyHiddenComponent: { + function performConcurrentWorkOnRoot(root, didTimeout) { { - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); + resetNestedUpdateFlag(); + } - if (flags & Passive$1) { - var current = finishedWork.alternate; - var instance = finishedWork.stateNode; - commitOffscreenPassiveMountEffects(current, finishedWork, instance); + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error("Should not already be working."); + } // Flush any pending passive effects before deciding which lanes to work on, + // in case they schedule additional work. + + var originalCallbackNode = root.callbackNode; + var didFlushPassiveEffects = flushPassiveEffects(); + + if (didFlushPassiveEffects) { + // Something in the passive effect phase may have canceled the current task. + // Check if the task node for this root was changed. + if (root.callbackNode !== originalCallbackNode) { + // The current task was canceled. Exit. We don't need to call + // `ensureRootIsScheduled` because the check above implies either that + // there's a new task, or that there's no remaining work on this root. + return null; } - } + } // Determine the next lanes to work on, using the fields stored + // on the root. + // TODO: This was already computed in the caller. Pass it as an argument. - break; - } + var lanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); + + if (lanes === NoLanes) { + // Defensive coding. This is never expected to happen. + return null; + } // We disable time-slicing in some cases: if the work has been CPU-bound + // for too long ("expired" work, to prevent starvation), or we're in + // sync-updates-by-default mode. + // TODO: We only check `didTimeout` defensively, to account for a Scheduler + // bug we're still investigating. Once the bug in Scheduler is fixed, + // we can remove this, since we track expiration ourselves. + + var shouldTimeSlice = + !includesBlockingLane(root, lanes) && + !includesExpiredLane(root, lanes) && + (disableSchedulerTimeoutInWorkLoop || !didTimeout); + var exitStatus = shouldTimeSlice + ? renderRootConcurrent(root, lanes) + : renderRootSync(root, lanes); + + if (exitStatus !== RootInProgress) { + var renderWasConcurrent = shouldTimeSlice; - case OffscreenComponent: { - // TODO: Pass `current` as argument to this function - var _instance3 = finishedWork.stateNode; - var nextState = finishedWork.memoizedState; - var isHidden = nextState !== null; + do { + if (exitStatus === RootDidNotComplete) { + // The render unwound without completing the tree. This happens in special + // cases where need to exit the current render without producing a + // consistent tree or committing. + markRootSuspended(root, lanes, NoLane); + } else { + // The render completed. + // Check if this render may have yielded to a concurrent event, and if so, + // confirm that any newly rendered stores are consistent. + // TODO: It's possible that even a concurrent render may never have yielded + // to the main thread, if it was fast enough, or if it expired. We could + // skip the consistency check in that case, too. + var finishedWork = root.current.alternate; - if (isHidden) { - if (_instance3._visibility & OffscreenPassiveEffectsConnected) { - // The effects are currently connected. Update them. - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); - } else { - if (finishedWork.mode & ConcurrentMode) { - // The effects are currently disconnected. Since the tree is hidden, - // don't connect them. This also applies to the initial render. - { - // "Atomic" effects are ones that need to fire on every commit, - // even during pre-rendering. An example is updating the reference - // count on cache instances. - recursivelyTraverseAtomicPassiveEffects( - finishedRoot, - finishedWork + if ( + renderWasConcurrent && + !isRenderConsistentWithExternalStores(finishedWork) + ) { + // A store was mutated in an interleaved event. Render again, + // synchronously, to block further mutations. + exitStatus = renderRootSync(root, lanes); // We assume the tree is now consistent because we didn't yield to any + // concurrent events. + + renderWasConcurrent = false; // Need to check the exit status again. + + continue; + } // Check if something threw + + if (exitStatus === RootErrored) { + var originallyAttemptedLanes = lanes; + var errorRetryLanes = getLanesToRetrySynchronouslyOnError( + root, + originallyAttemptedLanes ); + + if (errorRetryLanes !== NoLanes) { + lanes = errorRetryLanes; + exitStatus = recoverFromConcurrentError( + root, + originallyAttemptedLanes, + errorRetryLanes + ); + renderWasConcurrent = false; + } } - } else { - // Legacy Mode: Fire the effects even if the tree is hidden. - _instance3._visibility |= OffscreenPassiveEffectsConnected; - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); + + if (exitStatus === RootFatalErrored) { + var fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended(root, lanes, NoLane); + ensureRootIsScheduled(root); + throw fatalError; + } // We now have a consistent tree. The next step is either to commit it, + // or, if something suspended, wait to commit it after a timeout. + + root.finishedWork = finishedWork; + root.finishedLanes = lanes; + finishConcurrentRender(root, exitStatus, finishedWork, lanes); } - } - } else { - // Tree is visible - if (_instance3._visibility & OffscreenPassiveEffectsConnected) { - // The effects are currently connected. Update them. - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); - } else { - // The effects are currently disconnected. Reconnect them, while also - // firing effects inside newly mounted trees. This also applies to - // the initial render. - _instance3._visibility |= OffscreenPassiveEffectsConnected; - var includeWorkInProgressEffects = - (finishedWork.subtreeFlags & PassiveMask) !== NoFlags$1; - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); - } - } - if (flags & Passive$1) { - var _current = finishedWork.alternate; - commitOffscreenPassiveMountEffects(_current, finishedWork, _instance3); + break; + } while (true); } - break; + ensureRootIsScheduled(root); + return getContinuationForRoot(root, originalCallbackNode); } - case CacheComponent: { - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); + function recoverFromConcurrentError( + root, + originallyAttemptedLanes, + errorRetryLanes + ) { + // If an error occurred during hydration, discard server response and fall + // back to client side render. + // Before rendering again, save the errors from the previous attempt. + var errorsFromFirstAttempt = workInProgressRootConcurrentErrors; + var wasRootDehydrated = isRootDehydrated(root); + + if (wasRootDehydrated) { + // The shell failed to hydrate. Set a flag to force a client rendering + // during the next attempt. To do this, we call prepareFreshStack now + // to create the root work-in-progress fiber. This is a bit weird in terms + // of factoring, because it relies on renderRootSync not calling + // prepareFreshStack again in the call below, which happens because the + // root and lanes haven't changed. + // + // TODO: I think what we should do is set ForceClientRender inside + // throwException, like we do for nested Suspense boundaries. The reason + // it's here instead is so we can switch to the synchronous work loop, too. + // Something to consider for a future refactor. + var rootWorkInProgress = prepareFreshStack(root, errorRetryLanes); + rootWorkInProgress.flags |= ForceClientRender; - if (flags & Passive$1) { - // TODO: Pass `current` as argument to this function - var _current2 = finishedWork.alternate; - commitCachePassiveMountEffect(_current2, finishedWork); + { + errorHydratingContainer(); + } } - break; - } + var exitStatus = renderRootSync(root, errorRetryLanes); - case TracingMarkerComponent: { - if (enableTransitionTracing) { - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); + if (exitStatus !== RootErrored) { + // Successfully finished rendering on retry + if (workInProgressRootDidAttachPingListener && !wasRootDehydrated) { + // During the synchronous render, we attached additional ping listeners. + // This is highly suggestive of an uncached promise (though it's not the + // only reason this would happen). If it was an uncached promise, then + // it may have masked a downstream error from ocurring without actually + // fixing it. Example: + // + // use(Promise.resolve('uncached')) + // throw new Error('Oops!') + // + // When this happens, there's a conflict between blocking potential + // concurrent data races and unwrapping uncached promise values. We + // have to choose one or the other. Because the data race recovery is + // a last ditch effort, we'll disable it. + root.errorRecoveryDisabledLanes = mergeLanes( + root.errorRecoveryDisabledLanes, + originallyAttemptedLanes + ); // Mark the current render as suspended and force it to restart. Once + // these lanes finish successfully, we'll re-enable the error recovery + // mechanism for subsequent updates. - if (flags & Passive$1) { - commitTracingMarkerPassiveMountEffect(finishedWork); + workInProgressRootInterleavedUpdatedLanes |= originallyAttemptedLanes; + return RootSuspendedWithDelay; + } // The errors from the failed first attempt have been recovered. Add + // them to the collection of recoverable errors. We'll log them in the + // commit phase. + + var errorsFromSecondAttempt = workInProgressRootRecoverableErrors; + workInProgressRootRecoverableErrors = errorsFromFirstAttempt; // The errors from the second attempt should be queued after the errors + // from the first attempt, to preserve the causal sequence. + + if (errorsFromSecondAttempt !== null) { + queueRecoverableErrors(errorsFromSecondAttempt); } + } - break; - } // Intentional fallthrough to next branch + return exitStatus; } - default: { - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); - break; + function queueRecoverableErrors(errors) { + if (workInProgressRootRecoverableErrors === null) { + workInProgressRootRecoverableErrors = errors; + } else { + // $FlowFixMe[method-unbinding] + workInProgressRootRecoverableErrors.push.apply( + workInProgressRootRecoverableErrors, + errors + ); + } } - } -} - -function recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - parentFiber, - committedLanes, - committedTransitions, - includeWorkInProgressEffects -) { - // This function visits both newly finished work and nodes that were re-used - // from a previously committed tree. We cannot check non-static flags if the - // node was reused. - var childShouldIncludeWorkInProgressEffects = - includeWorkInProgressEffects && - (parentFiber.subtreeFlags & PassiveMask) !== NoFlags$1; // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) - - var prevDebugFiber = getCurrentFiber(); - var child = parentFiber.child; - - while (child !== null) { - reconnectPassiveEffects( - finishedRoot, - child, - committedLanes, - committedTransitions, - childShouldIncludeWorkInProgressEffects - ); - child = child.sibling; - } - setCurrentFiber(prevDebugFiber); -} + function finishConcurrentRender(root, exitStatus, finishedWork, lanes) { + // TODO: The fact that most of these branches are identical suggests that some + // of the exit statuses are not best modeled as exit statuses and should be + // tracked orthogonally. + switch (exitStatus) { + case RootInProgress: + case RootFatalErrored: { + throw new Error("Root did not complete. This is a bug in React."); + } -function reconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, // This function visits both newly finished work and nodes that were re-used - // from a previously committed tree. We cannot check non-static flags if the - // node was reused. - includeWorkInProgressEffects -) { - var flags = finishedWork.flags; - - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); // TODO: Check for PassiveStatic flag + case RootSuspendedWithDelay: { + if (includesOnlyTransitions(lanes)) { + // This is a transition, so we should exit without committing a + // placeholder and without scheduling a timeout. Delay indefinitely + // until we receive more data. + markRootSuspended(root, lanes, workInProgressDeferredLane); + return; + } // Commit the placeholder. - commitHookPassiveMountEffects(finishedWork, Passive); - break; - } - // Unlike commitPassiveMountOnFiber, we don't need to handle HostRoot - // because this function only visits nodes that are inside an - // Offscreen fiber. - // case HostRoot: { - // ... - // } + break; + } - case LegacyHiddenComponent: { - { - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); + case RootErrored: + case RootSuspended: + case RootCompleted: { + break; + } - if (includeWorkInProgressEffects && flags & Passive$1) { - // TODO: Pass `current` as argument to this function - var current = finishedWork.alternate; - var instance = finishedWork.stateNode; - commitOffscreenPassiveMountEffects(current, finishedWork, instance); + default: { + throw new Error("Unknown root exit status."); } } - break; - } - - case OffscreenComponent: { - var _instance4 = finishedWork.stateNode; - var nextState = finishedWork.memoizedState; - var isHidden = nextState !== null; - - if (isHidden) { - if (_instance4._visibility & OffscreenPassiveEffectsConnected) { - // The effects are currently connected. Update them. - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); - } else { - if (finishedWork.mode & ConcurrentMode) { - // The effects are currently disconnected. Since the tree is hidden, - // don't connect them. This also applies to the initial render. - { - // "Atomic" effects are ones that need to fire on every commit, - // even during pre-rendering. An example is updating the reference - // count on cache instances. - recursivelyTraverseAtomicPassiveEffects( - finishedRoot, - finishedWork - ); - } - } else { - // Legacy Mode: Fire the effects even if the tree is hidden. - _instance4._visibility |= OffscreenPassiveEffectsConnected; - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects + if (shouldForceFlushFallbacksInDEV()) { + // We're inside an `act` scope. Commit immediately. + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + workInProgressDeferredLane + ); + } else { + if ( + includesOnlyRetries(lanes) && + (alwaysThrottleRetries || exitStatus === RootSuspended) + ) { + // This render only included retries, no updates. Throttle committing + // retries so that we don't show too many loading states too quickly. + var msUntilTimeout = + globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now$1(); // Don't bother with a very short suspense time. + + if (msUntilTimeout > 10) { + markRootSuspended(root, lanes, workInProgressDeferredLane); + var nextLanes = getNextLanes(root, NoLanes); + + if (nextLanes !== NoLanes) { + // There's additional work we can do on this root. We might as well + // attempt to work on that while we're suspended. + return; + } // The render is suspended, it hasn't timed out, and there's no + // lower priority work to do. Instead of committing the fallback + // immediately, wait for more data to arrive. + // TODO: Combine retry throttling with Suspensey commits. Right now they + // run one after the other. + + root.timeoutHandle = scheduleTimeout( + commitRootWhenReady.bind( + null, + root, + finishedWork, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes, + workInProgressDeferredLane + ), + msUntilTimeout ); + return; } } - } else { - // Tree is visible - // Since we're already inside a reconnecting tree, it doesn't matter - // whether the effects are currently connected. In either case, we'll - // continue traversing the tree and firing all the effects. - // - // We do need to set the "connected" flag on the instance, though. - _instance4._visibility |= OffscreenPassiveEffectsConnected; - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, + + commitRootWhenReady( + root, finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes, + workInProgressDeferredLane ); } - - if (includeWorkInProgressEffects && flags & Passive$1) { - // TODO: Pass `current` as argument to this function - var _current3 = finishedWork.alternate; - commitOffscreenPassiveMountEffects(_current3, finishedWork, _instance4); - } - - break; } - case CacheComponent: { - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); - - if (includeWorkInProgressEffects && flags & Passive$1) { - // TODO: Pass `current` as argument to this function - var _current4 = finishedWork.alternate; - commitCachePassiveMountEffect(_current4, finishedWork); - } + function commitRootWhenReady( + root, + finishedWork, + recoverableErrors, + transitions, + lanes, + spawnedLane + ) { + // TODO: Combine retry throttling with Suspensey commits. Right now they run + // one after the other. + if (includesOnlyNonUrgentLanes(lanes)) { + // the suspensey resources. The renderer is responsible for accumulating + // all the load events. This all happens in a single synchronous + // transaction, so it track state in its own module scope. + + accumulateSuspenseyCommit(finishedWork); // At the end, ask the renderer if it's ready to commit, or if we should + // suspend. If it's not ready, it will return a callback to subscribe to + // a ready event. + + var schedulePendingCommit = waitForCommitToBeReady(); + + if (schedulePendingCommit !== null) { + // NOTE: waitForCommitToBeReady returns a subscribe function so that we + // only allocate a function if the commit isn't ready yet. The other + // pattern would be to always pass a callback to waitForCommitToBeReady. + // Not yet ready to commit. Delay the commit until the renderer notifies + // us that it's ready. This will be canceled if we start work on the + // root again. + root.cancelPendingCommit = schedulePendingCommit( + commitRoot.bind(null, root, recoverableErrors, transitions) + ); + markRootSuspended(root, lanes, spawnedLane); + return; + } + } // Otherwise, commit immediately. - break; + commitRoot(root, recoverableErrors, transitions, spawnedLane); } - case TracingMarkerComponent: { - if (enableTransitionTracing) { - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); + function isRenderConsistentWithExternalStores(finishedWork) { + // Search the rendered tree for external store reads, and check whether the + // stores were mutated in a concurrent event. Intentionally using an iterative + // loop instead of recursion so we can exit early. + var node = finishedWork; - if (includeWorkInProgressEffects && flags & Passive$1) { - commitTracingMarkerPassiveMountEffect(finishedWork); - } + while (true) { + if (node.flags & StoreConsistency) { + var updateQueue = node.updateQueue; - break; - } // Intentional fallthrough to next branch - } + if (updateQueue !== null) { + var checks = updateQueue.stores; - default: { - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); - break; - } - } -} + if (checks !== null) { + for (var i = 0; i < checks.length; i++) { + var check = checks[i]; + var getSnapshot = check.getSnapshot; + var renderedValue = check.value; + + try { + if (!objectIs(getSnapshot(), renderedValue)) { + // Found an inconsistent store. + return false; + } + } catch (error) { + // If `getSnapshot` throws, return `false`. This will schedule + // a re-render, and the error will be rethrown during render. + return false; + } + } + } + } + } -function recursivelyTraverseAtomicPassiveEffects( - finishedRoot, - parentFiber, - committedLanes, - committedTransitions -) { - // "Atomic" effects are ones that need to fire on every commit, even during - // pre-rendering. We call this function when traversing a hidden tree whose - // regular effects are currently disconnected. - var prevDebugFiber = getCurrentFiber(); // TODO: Add special flag for atomic effects + var child = node.child; - if (parentFiber.subtreeFlags & PassiveMask) { - var child = parentFiber.child; + if (node.subtreeFlags & StoreConsistency && child !== null) { + child.return = node; + node = child; + continue; + } - while (child !== null) { - setCurrentFiber(child); - commitAtomicPassiveEffects(finishedRoot, child); - child = child.sibling; - } - } + if (node === finishedWork) { + return true; + } - setCurrentFiber(prevDebugFiber); -} + while (node.sibling === null) { + if (node.return === null || node.return === finishedWork) { + return true; + } -function commitAtomicPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions -) { - // "Atomic" effects are ones that need to fire on every commit, even during - // pre-rendering. We call this function when traversing a hidden tree whose - // regular effects are currently disconnected. - var flags = finishedWork.flags; - - switch (finishedWork.tag) { - case OffscreenComponent: { - recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork); - - if (flags & Passive$1) { - // TODO: Pass `current` as argument to this function - var current = finishedWork.alternate; - var instance = finishedWork.stateNode; - commitOffscreenPassiveMountEffects(current, finishedWork, instance); - } + node = node.return; + } - break; + node.sibling.return = node.return; + node = node.sibling; + } // Flow doesn't know this is unreachable, but eslint does + // eslint-disable-next-line no-unreachable + + return true; } - case CacheComponent: { - recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork); + function markRootSuspended(root, suspendedLanes, spawnedLane) { + // When suspending, we should always exclude lanes that were pinged or (more + // rarely, since we try to avoid it) updated during the render phase. + // TODO: Lol maybe there's a better way to factor this besides this + // obnoxiously named function :) + suspendedLanes = removeLanes( + suspendedLanes, + workInProgressRootPingedLanes + ); + suspendedLanes = removeLanes( + suspendedLanes, + workInProgressRootInterleavedUpdatedLanes + ); + markRootSuspended$1(root, suspendedLanes, spawnedLane); + } // This is the entry point for synchronous tasks that don't go + // through Scheduler - if (flags & Passive$1) { - // TODO: Pass `current` as argument to this function - var _current5 = finishedWork.alternate; - commitCachePassiveMountEffect(_current5, finishedWork); + function performSyncWorkOnRoot(root, lanes) { + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error("Should not already be working."); } - break; - } - - default: { - recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork); - break; - } - } -} + var didFlushPassiveEffects = flushPassiveEffects(); -function commitPassiveUnmountEffects(finishedWork) { - setCurrentFiber(finishedWork); - commitPassiveUnmountOnFiber(finishedWork); - resetCurrentFiber(); -} // If we're inside a brand new tree, or a tree that was already visible, then we -// should only suspend host components that have a ShouldSuspendCommit flag. -// Components without it haven't changed since the last commit, so we can skip -// over those. -// -// When we enter a tree that is being revealed (going from hidden -> visible), -// we need to suspend _any_ component that _may_ suspend. Even if they're -// already in the "current" tree. Because their visibility has changed, the -// browser may not have prerendered them yet. So we check the MaySuspendCommit -// flag instead. - -var suspenseyCommitFlag = ShouldSuspendCommit; -function accumulateSuspenseyCommit(finishedWork) { - accumulateSuspenseyCommitOnFiber(finishedWork); -} + if (didFlushPassiveEffects) { + // If passive effects were flushed, exit to the outer work loop in the root + // scheduler, so we can recompute the priority. + // TODO: We don't actually need this `ensureRootIsScheduled` call because + // this path is only reachable if the root is already part of the schedule. + // I'm including it only for consistency with the other exit points from + // this function. Can address in a subsequent refactor. + ensureRootIsScheduled(root); + return null; + } -function recursivelyAccumulateSuspenseyCommit(parentFiber) { - if (parentFiber.subtreeFlags & suspenseyCommitFlag) { - var child = parentFiber.child; + { + syncNestedUpdateFlag(); + } - while (child !== null) { - accumulateSuspenseyCommitOnFiber(child); - child = child.sibling; - } - } -} + var exitStatus = renderRootSync(root, lanes); -function accumulateSuspenseyCommitOnFiber(fiber) { - switch (fiber.tag) { - case HostHoistable: { - recursivelyAccumulateSuspenseyCommit(fiber); + if (root.tag !== LegacyRoot && exitStatus === RootErrored) { + // If something threw an error, try rendering one more time. We'll render + // synchronously to block concurrent data mutations, and we'll includes + // all pending updates are included. If it still fails after the second + // attempt, we'll give up and commit the resulting tree. + var originallyAttemptedLanes = lanes; + var errorRetryLanes = getLanesToRetrySynchronouslyOnError( + root, + originallyAttemptedLanes + ); - if (fiber.flags & suspenseyCommitFlag) { - if (fiber.memoizedState !== null) { - suspendResource(); + if (errorRetryLanes !== NoLanes) { + lanes = errorRetryLanes; + exitStatus = recoverFromConcurrentError( + root, + originallyAttemptedLanes, + errorRetryLanes + ); } } - break; - } + if (exitStatus === RootFatalErrored) { + var fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended(root, lanes, NoLane); + ensureRootIsScheduled(root); + throw fatalError; + } + + if (exitStatus === RootDidNotComplete) { + // The render unwound without completing the tree. This happens in special + // cases where need to exit the current render without producing a + // consistent tree or committing. + markRootSuspended(root, lanes, NoLane); + ensureRootIsScheduled(root); + return null; + } // We now have a consistent tree. Because this is a sync render, we + // will commit it even if something suspended. - case HostComponent: { - recursivelyAccumulateSuspenseyCommit(fiber); + var finishedWork = root.current.alternate; + root.finishedWork = finishedWork; + root.finishedLanes = lanes; + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + workInProgressDeferredLane + ); // Before exiting, make sure there's a callback scheduled for the next + // pending level. - break; + ensureRootIsScheduled(root); + return null; } + function getExecutionContext() { + return executionContext; + } + // Warning, this opts-out of checking the function body. + // eslint-disable-next-line no-unused-vars + // eslint-disable-next-line no-redeclare + // eslint-disable-next-line no-redeclare - case HostRoot: - case HostPortal: { - { - recursivelyAccumulateSuspenseyCommit(fiber); + function flushSync(fn) { + // In legacy mode, we flush pending passive effects at the beginning of the + // next event, not at the end of the previous one. + if ( + rootWithPendingPassiveEffects !== null && + rootWithPendingPassiveEffects.tag === LegacyRoot && + (executionContext & (RenderContext | CommitContext)) === NoContext + ) { + flushPassiveEffects(); } - break; - } + var prevExecutionContext = executionContext; + executionContext |= BatchedContext; + var prevTransition = ReactCurrentBatchConfig.transition; + var previousPriority = getCurrentUpdatePriority(); - case OffscreenComponent: { - var isHidden = fiber.memoizedState !== null; + try { + ReactCurrentBatchConfig.transition = null; + setCurrentUpdatePriority(DiscreteEventPriority); - if (isHidden); - else { - var current = fiber.alternate; - var wasHidden = current !== null && current.memoizedState !== null; - - if (wasHidden) { - // This tree is being revealed. Visit all newly visible suspensey - // instances, even if they're in the current tree. - var prevFlags = suspenseyCommitFlag; - suspenseyCommitFlag = MaySuspendCommit; - recursivelyAccumulateSuspenseyCommit(fiber); - suspenseyCommitFlag = prevFlags; + if (fn) { + return fn(); } else { - recursivelyAccumulateSuspenseyCommit(fiber); + return undefined; } - } + } finally { + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig.transition = prevTransition; + executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. + // Note that this will happen even if batchedUpdates is higher up + // the stack. - break; + if ( + (executionContext & (RenderContext | CommitContext)) === + NoContext + ) { + flushSyncWorkOnAllRoots(); + } + } } + function isInvalidExecutionContextForEventFunction() { + // Used to throw if certain APIs are called from the wrong context. + return (executionContext & RenderContext) !== NoContext; + } // This is called by the HiddenContext module when we enter or leave a + // hidden subtree. The stack logic is managed there because that's the only + // place that ever modifies it. Which module it lives in doesn't matter for + // performance because this function will get inlined regardless - default: { - recursivelyAccumulateSuspenseyCommit(fiber); + function setEntangledRenderLanes(newEntangledRenderLanes) { + entangledRenderLanes = newEntangledRenderLanes; } - } -} - -function detachAlternateSiblings(parentFiber) { - // A fiber was deleted from this parent fiber, but it's still part of the - // previous (alternate) parent fiber's list of children. Because children - // are a linked list, an earlier sibling that's still alive will be - // connected to the deleted fiber via its `alternate`: - // - // live fiber --alternate--> previous live fiber --sibling--> deleted - // fiber - // - // We can't disconnect `alternate` on nodes that haven't been deleted yet, - // but we can disconnect the `sibling` and `child` pointers. - var previousFiber = parentFiber.alternate; - - if (previousFiber !== null) { - var detachedChild = previousFiber.child; - - if (detachedChild !== null) { - previousFiber.child = null; - - do { - // $FlowFixMe[incompatible-use] found when upgrading Flow - var detachedSibling = detachedChild.sibling; // $FlowFixMe[incompatible-use] found when upgrading Flow - - detachedChild.sibling = null; - detachedChild = detachedSibling; - } while (detachedChild !== null); + function getEntangledRenderLanes() { + return entangledRenderLanes; } - } -} - -function commitHookPassiveUnmountEffects( - finishedWork, - nearestMountedAncestor, - hookFlags -) { - if (shouldProfile(finishedWork)) { - startPassiveEffectTimer(); - commitHookEffectListUnmount( - hookFlags, - finishedWork, - nearestMountedAncestor - ); - recordPassiveEffectDuration(finishedWork); - } else { - commitHookEffectListUnmount( - hookFlags, - finishedWork, - nearestMountedAncestor - ); - } -} -function recursivelyTraversePassiveUnmountEffects(parentFiber) { - // Deletions effects can be scheduled on any fiber type. They need to happen - // before the children effects have fired. - var deletions = parentFiber.deletions; + function resetWorkInProgressStack() { + if (workInProgress === null) return; + var interruptedWork; - if ((parentFiber.flags & ChildDeletion) !== NoFlags$1) { - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var childToDelete = deletions[i]; // TODO: Convert this to use recursion + if (workInProgressSuspendedReason === NotSuspended) { + // Normal case. Work-in-progress hasn't started yet. Unwind all + // its parents. + interruptedWork = workInProgress.return; + } else { + // Work-in-progress is in suspended state. Reset the work loop and unwind + // both the suspended fiber and all its parents. + resetSuspendedWorkLoopOnUnwind(workInProgress); + interruptedWork = workInProgress; + } - nextEffect = childToDelete; - commitPassiveUnmountEffectsInsideOfDeletedTree_begin( - childToDelete, - parentFiber - ); + while (interruptedWork !== null) { + var current = interruptedWork.alternate; + unwindInterruptedWork(current, interruptedWork); + interruptedWork = interruptedWork.return; } + + workInProgress = null; } - detachAlternateSiblings(parentFiber); - } + function prepareFreshStack(root, lanes) { + root.finishedWork = null; + root.finishedLanes = NoLanes; + var timeoutHandle = root.timeoutHandle; - var prevDebugFiber = getCurrentFiber(); // TODO: Split PassiveMask into separate masks for mount and unmount? + if (timeoutHandle !== noTimeout) { + // The root previous suspended and scheduled a timeout to commit a fallback + // state. Now that we have additional work, cancel the timeout. + root.timeoutHandle = noTimeout; // $FlowFixMe[incompatible-call] Complains noTimeout is not a TimeoutID, despite the check above - if (parentFiber.subtreeFlags & PassiveMask) { - var child = parentFiber.child; + cancelTimeout(timeoutHandle); + } - while (child !== null) { - setCurrentFiber(child); - commitPassiveUnmountOnFiber(child); - child = child.sibling; - } - } + var cancelPendingCommit = root.cancelPendingCommit; - setCurrentFiber(prevDebugFiber); -} + if (cancelPendingCommit !== null) { + root.cancelPendingCommit = null; + cancelPendingCommit(); + } -function commitPassiveUnmountOnFiber(finishedWork) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - recursivelyTraversePassiveUnmountEffects(finishedWork); + resetWorkInProgressStack(); + workInProgressRoot = root; + var rootWorkInProgress = createWorkInProgress(root.current, null); + workInProgress = rootWorkInProgress; + workInProgressRootRenderLanes = lanes; + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + workInProgressRootDidAttachPingListener = false; + workInProgressRootExitStatus = RootInProgress; + workInProgressRootFatalError = null; + workInProgressRootSkippedLanes = NoLanes; + workInProgressRootInterleavedUpdatedLanes = NoLanes; + workInProgressRootPingedLanes = NoLanes; + workInProgressDeferredLane = NoLane; + workInProgressRootConcurrentErrors = null; + workInProgressRootRecoverableErrors = null; // Get the lanes that are entangled with whatever we're about to render. We + // track these separately so we can distinguish the priority of the render + // task from the priority of the lanes it is entangled with. For example, a + // transition may not be allowed to finish unless it includes the Sync lane, + // which is currently suspended. We should be able to render the Transition + // and Sync lane in the same batch, but at Transition priority, because the + // Sync lane already suspended. - if (finishedWork.flags & Passive$1) { - commitHookPassiveUnmountEffects( - finishedWork, - finishedWork.return, - Passive | HasEffect - ); + entangledRenderLanes = getEntangledLanes(root, lanes); + finishQueueingConcurrentUpdates(); + + { + ReactStrictModeWarnings.discardPendingWarnings(); } - break; + return rootWorkInProgress; } - case OffscreenComponent: { - var instance = finishedWork.stateNode; - var nextState = finishedWork.memoizedState; - var isHidden = nextState !== null; + function resetSuspendedWorkLoopOnUnwind(fiber) { + // Reset module-level state that was set during the render phase. + resetContextDependencies(); + resetHooksOnUnwind(fiber); + resetChildReconcilerOnUnwind(); + } - if ( - isHidden && - instance._visibility & OffscreenPassiveEffectsConnected && // For backwards compatibility, don't unmount when a tree suspends. In - // the future we may change this to unmount after a delay. - (finishedWork.return === null || - finishedWork.return.tag !== SuspenseComponent) - ) { - // The effects are currently connected. Disconnect them. - // TODO: Add option or heuristic to delay before disconnecting the - // effects. Then if the tree reappears before the delay has elapsed, we - // can skip toggling the effects entirely. - instance._visibility &= ~OffscreenPassiveEffectsConnected; - recursivelyTraverseDisconnectPassiveEffects(finishedWork); + function handleThrow(root, thrownValue) { + // A component threw an exception. Usually this is because it suspended, but + // it also includes regular program errors. + // + // We're either going to unwind the stack to show a Suspense or error + // boundary, or we're going to replay the component again. Like after a + // promise resolves. + // + // Until we decide whether we're going to unwind or replay, we should preserve + // the current state of the work loop without resetting anything. + // + // If we do decide to unwind the stack, module-level variables will be reset + // in resetSuspendedWorkLoopOnUnwind. + // These should be reset immediately because they're only supposed to be set + // when React is executing user code. + resetHooksAfterThrow(); + resetCurrentFiber(); + ReactCurrentOwner.current = null; + + if (thrownValue === SuspenseException) { + // This is a special type of exception used for Suspense. For historical + // reasons, the rest of the Suspense implementation expects the thrown value + // to be a thenable, because before `use` existed that was the (unstable) + // API for suspending. This implementation detail can change later, once we + // deprecate the old API in favor of `use`. + thrownValue = getSuspendedThenable(); + workInProgressSuspendedReason = + shouldRemainOnPreviousScreen() && // Check if there are other pending updates that might possibly unblock this + // component from suspending. This mirrors the check in + // renderDidSuspendDelayIfPossible. We should attempt to unify them somehow. + // TODO: Consider unwinding immediately, using the + // SuspendedOnHydration mechanism. + !includesNonIdleWork(workInProgressRootSkippedLanes) && + !includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes) // Suspend work loop until data resolves + ? SuspendedOnData // Don't suspend work loop, except to check if the data has + : // immediately resolved (i.e. in a microtask). Otherwise, trigger the + // nearest Suspense fallback. + SuspendedOnImmediate; + } else if (thrownValue === SuspenseyCommitException) { + thrownValue = getSuspendedThenable(); + workInProgressSuspendedReason = SuspendedOnInstance; + } else if (thrownValue === SelectiveHydrationException) { + // An update flowed into a dehydrated boundary. Before we can apply the + // update, we need to finish hydrating. Interrupt the work-in-progress + // render so we can restart at the hydration lane. + // + // The ideal implementation would be able to switch contexts without + // unwinding the current stack. + // + // We could name this something more general but as of now it's the only + // case where we think this should happen. + workInProgressSuspendedReason = SuspendedOnHydration; } else { - recursivelyTraversePassiveUnmountEffects(finishedWork); + // This is a regular error. + var isWakeable = + thrownValue !== null && + typeof thrownValue === "object" && + typeof thrownValue.then === "function"; + workInProgressSuspendedReason = isWakeable // A wakeable object was thrown by a legacy Suspense implementation. + ? // This has slightly different behavior than suspending with `use`. + SuspendedOnDeprecatedThrowPromise // This is a regular error. If something earlier in the component already + : // suspended, we must clear the thenable state to unblock the work loop. + SuspendedOnError; + } + + workInProgressThrownValue = thrownValue; + var erroredWork = workInProgress; + + if (erroredWork === null) { + // This is a fatal error + workInProgressRootExitStatus = RootFatalErrored; + workInProgressRootFatalError = thrownValue; + return; } - break; - } - - default: { - recursivelyTraversePassiveUnmountEffects(finishedWork); - break; - } - } -} + if (erroredWork.mode & ProfileMode) { + // Record the time spent rendering before an error was thrown. This + // avoids inaccurate Profiler durations in the case of a + // suspended render. + stopProfilerTimerIfRunningAndRecordDelta(erroredWork, true); + } -function recursivelyTraverseDisconnectPassiveEffects(parentFiber) { - // Deletions effects can be scheduled on any fiber type. They need to happen - // before the children effects have fired. - var deletions = parentFiber.deletions; + if (enableSchedulingProfiler) { + markComponentRenderStopped(); - if ((parentFiber.flags & ChildDeletion) !== NoFlags$1) { - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var childToDelete = deletions[i]; // TODO: Convert this to use recursion + switch (workInProgressSuspendedReason) { + case SuspendedOnError: { + markComponentErrored( + erroredWork, + thrownValue, + workInProgressRootRenderLanes + ); + break; + } - nextEffect = childToDelete; - commitPassiveUnmountEffectsInsideOfDeletedTree_begin( - childToDelete, - parentFiber - ); + case SuspendedOnData: + case SuspendedOnImmediate: + case SuspendedOnDeprecatedThrowPromise: + case SuspendedAndReadyToContinue: { + var wakeable = thrownValue; + markComponentSuspended( + erroredWork, + wakeable, + workInProgressRootRenderLanes + ); + break; + } + } } } - detachAlternateSiblings(parentFiber); - } + function shouldRemainOnPreviousScreen() { + // This is asking whether it's better to suspend the transition and remain + // on the previous screen, versus showing a fallback as soon as possible. It + // takes into account both the priority of render and also whether showing a + // fallback would produce a desirable user experience. + var handler = getSuspenseHandler(); - var prevDebugFiber = getCurrentFiber(); // TODO: Check PassiveStatic flag - - var child = parentFiber.child; + if (handler === null) { + // There's no Suspense boundary that can provide a fallback. We have no + // choice but to remain on the previous screen. + // NOTE: We do this even for sync updates, for lack of any better option. In + // the future, we may change how we handle this, like by putting the whole + // root into a "detached" mode. + return true; + } // TODO: Once `use` has fully replaced the `throw promise` pattern, we should + // be able to remove the equivalent check in finishConcurrentRender, and rely + // just on this one. + + if (includesOnlyTransitions(workInProgressRootRenderLanes)) { + if (getShellBoundary() === null) { + // We're rendering inside the "shell" of the app. Activating the nearest + // fallback would cause visible content to disappear. It's better to + // suspend the transition and remain on the previous screen. + return true; + } else { + // We're rendering content that wasn't part of the previous screen. + // Rather than block the transition, it's better to show a fallback as + // soon as possible. The appearance of any nested fallbacks will be + // throttled to avoid jank. + return false; + } + } - while (child !== null) { - setCurrentFiber(child); - disconnectPassiveEffect(child); - child = child.sibling; - } + if ( + includesOnlyRetries(workInProgressRootRenderLanes) || // In this context, an OffscreenLane counts as a Retry + // TODO: It's become increasingly clear that Retries and Offscreen are + // deeply connected. They probably can be unified further. + includesSomeLane(workInProgressRootRenderLanes, OffscreenLane) + ) { + // During a retry, we can suspend rendering if the nearest Suspense boundary + // is the boundary of the "shell", because we're guaranteed not to block + // any new content from appearing. + // + // The reason we must check if this is a retry is because it guarantees + // that suspending the work loop won't block an actual update, because + // retries don't "update" anything; they fill in fallbacks that were left + // behind by a previous transition. + return handler === getShellBoundary(); + } // For all other Lanes besides Transitions and Retries, we should not wait + // for the data to load. - setCurrentFiber(prevDebugFiber); -} + return false; + } -function disconnectPassiveEffect(finishedWork) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - // TODO: Check PassiveStatic flag - commitHookPassiveUnmountEffects( - finishedWork, - finishedWork.return, - Passive - ); // When disconnecting passive effects, we fire the effects in the same - // order as during a deletiong: parent before child + function pushDispatcher(container) { + var prevDispatcher = ReactCurrentDispatcher.current; + ReactCurrentDispatcher.current = ContextOnlyDispatcher; - recursivelyTraverseDisconnectPassiveEffects(finishedWork); - break; + if (prevDispatcher === null) { + // The React isomorphic package does not include a default dispatcher. + // Instead the first renderer will lazily attach one, in order to give + // nicer error messages. + return ContextOnlyDispatcher; + } else { + return prevDispatcher; + } } - case OffscreenComponent: { - var instance = finishedWork.stateNode; + function popDispatcher(prevDispatcher) { + ReactCurrentDispatcher.current = prevDispatcher; + } - if (instance._visibility & OffscreenPassiveEffectsConnected) { - instance._visibility &= ~OffscreenPassiveEffectsConnected; - recursivelyTraverseDisconnectPassiveEffects(finishedWork); + function pushCacheDispatcher() { + { + var prevCacheDispatcher = ReactCurrentCache.current; + ReactCurrentCache.current = DefaultCacheDispatcher; + return prevCacheDispatcher; } - - break; } - default: { - recursivelyTraverseDisconnectPassiveEffects(finishedWork); - break; + function popCacheDispatcher(prevCacheDispatcher) { + { + ReactCurrentCache.current = prevCacheDispatcher; + } } - } -} -function commitPassiveUnmountEffectsInsideOfDeletedTree_begin( - deletedSubtreeRoot, - nearestMountedAncestor -) { - while (nextEffect !== null) { - var fiber = nextEffect; // Deletion effects fire in parent -> child order - // TODO: Check if fiber has a PassiveStatic flag - - setCurrentFiber(fiber); - commitPassiveUnmountInsideDeletedTreeOnFiber(fiber, nearestMountedAncestor); - resetCurrentFiber(); - var child = fiber.child; // TODO: Only traverse subtree if it has a PassiveStatic flag. - - if (child !== null) { - child.return = fiber; - nextEffect = child; - } else { - commitPassiveUnmountEffectsInsideOfDeletedTree_complete( - deletedSubtreeRoot + function markCommitTimeOfFallback() { + globalMostRecentFallbackTime = now$1(); + } + function markSkippedUpdateLanes(lane) { + workInProgressRootSkippedLanes = mergeLanes( + lane, + workInProgressRootSkippedLanes ); } - } -} - -function commitPassiveUnmountEffectsInsideOfDeletedTree_complete( - deletedSubtreeRoot -) { - while (nextEffect !== null) { - var fiber = nextEffect; - var sibling = fiber.sibling; - var returnFiber = fiber.return; // Recursively traverse the entire deleted tree and clean up fiber fields. - // This is more aggressive than ideal, and the long term goal is to only - // have to detach the deleted tree at the root. - - detachFiberAfterEffects(fiber); - - if (fiber === deletedSubtreeRoot) { - nextEffect = null; - return; + function renderDidSuspend() { + if (workInProgressRootExitStatus === RootInProgress) { + workInProgressRootExitStatus = RootSuspended; + } } + function renderDidSuspendDelayIfPossible() { + workInProgressRootExitStatus = RootSuspendedWithDelay; // Check if there are updates that we skipped tree that might have unblocked + // this render. - if (sibling !== null) { - sibling.return = returnFiber; - nextEffect = sibling; - return; + if ( + (includesNonIdleWork(workInProgressRootSkippedLanes) || + includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes)) && + workInProgressRoot !== null + ) { + // Mark the current render as suspended so that we switch to working on + // the updates that were skipped. Usually we only suspend at the end of + // the render phase. + // TODO: We should probably always mark the root as suspended immediately + // (inside this function), since by suspending at the end of the render + // phase introduces a potential mistake where we suspend lanes that were + // pinged or updated while we were rendering. + // TODO: Consider unwinding immediately, using the + // SuspendedOnHydration mechanism. + markRootSuspended( + workInProgressRoot, + workInProgressRootRenderLanes, + workInProgressDeferredLane + ); + } } + function renderDidError(error) { + if (workInProgressRootExitStatus !== RootSuspendedWithDelay) { + workInProgressRootExitStatus = RootErrored; + } - nextEffect = returnFiber; - } -} - -function commitPassiveUnmountInsideDeletedTreeOnFiber( - current, - nearestMountedAncestor -) { - switch (current.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - commitHookPassiveUnmountEffects(current, nearestMountedAncestor, Passive); - break; - } - // TODO: run passive unmount effects when unmounting a root. - // Because passive unmount effects are not currently run, - // the cache instance owned by the root will never be freed. - // When effects are run, the cache should be freed here: - // case HostRoot: { - // if (enableCache) { - // const cache = current.memoizedState.cache; - // releaseCache(cache); - // } - // break; - // } - - case LegacyHiddenComponent: - case OffscreenComponent: { - { - if ( - current.memoizedState !== null && - current.memoizedState.cachePool !== null - ) { - var cache = current.memoizedState.cachePool.pool; // Retain/release the cache used for pending (suspended) nodes. - // Note that this is only reached in the non-suspended/visible case: - // when the content is suspended/hidden, the retain/release occurs - // via the parent Suspense component (see case above). + if (workInProgressRootConcurrentErrors === null) { + workInProgressRootConcurrentErrors = [error]; + } else { + workInProgressRootConcurrentErrors.push(error); + } + } // Called during render to determine if anything has suspended. + // Returns false if we're not sure. + + function renderHasNotSuspendedYet() { + // If something errored or completed, we can't really be sure, + // so those are false. + return workInProgressRootExitStatus === RootInProgress; + } // TODO: Over time, this function and renderRootConcurrent have become more + // and more similar. Not sure it makes sense to maintain forked paths. Consider + // unifying them again. + + function renderRootSync(root, lanes) { + var prevExecutionContext = executionContext; + executionContext |= RenderContext; + var prevDispatcher = pushDispatcher(); + var prevCacheDispatcher = pushCacheDispatcher(); // If the root or lanes have changed, throw out the existing stack + // and prepare a fresh one. Otherwise we'll continue where we left off. - if (cache != null) { - retainCache(cache); + if ( + workInProgressRoot !== root || + workInProgressRootRenderLanes !== lanes + ) { + { + if (isDevToolsPresent) { + var memoizedUpdaters = root.memoizedUpdaters; + + if (memoizedUpdaters.size > 0) { + restorePendingUpdaters(root, workInProgressRootRenderLanes); + memoizedUpdaters.clear(); + } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set. + // If we bailout on this work, we'll move them back (like above). + // It's important to move them now in case the work spawns more work at the same priority with different updaters. + // That way we can keep the current update and future updates separate. + + movePendingFibersToMemoized(root, lanes); } } + + workInProgressTransitions = getTransitionsForLanes(root, lanes); + prepareFreshStack(root, lanes); } - break; - } + { + if (enableDebugTracing) { + logRenderStarted(lanes); + } + } - case SuspenseComponent: { - if (enableTransitionTracing) { - // We need to mark this fiber's parents as deleted - var offscreenFiber = current.child; - var instance = offscreenFiber.stateNode; - var transitions = instance._transitions; + if (enableSchedulingProfiler) { + markRenderStarted(lanes); + } - if (transitions !== null) { - var abortReason = { - reason: "suspense", - name: current.memoizedProps.unstable_name || null - }; + var didSuspendInShell = false; + outer: do { + try { if ( - current.memoizedState === null || - current.memoizedState.dehydrated === null + workInProgressSuspendedReason !== NotSuspended && + workInProgress !== null ) { - abortParentMarkerTransitionsForDeletedFiber( - offscreenFiber, - abortReason, - transitions, - instance, - true - ); + // The work loop is suspended. During a synchronous render, we don't + // yield to the main thread. Immediately unwind the stack. This will + // trigger either a fallback or an error boundary. + // TODO: For discrete and "default" updates (anything that's not + // flushSync), we want to wait for the microtasks the flush before + // unwinding. Will probably implement this using renderRootConcurrent, + // or merge renderRootSync and renderRootConcurrent into the same + // function and fork the behavior some other way. + var unitOfWork = workInProgress; + var thrownValue = workInProgressThrownValue; + + switch (workInProgressSuspendedReason) { + case SuspendedOnHydration: { + // Selective hydration. An update flowed into a dehydrated tree. + // Interrupt the current render so the work loop can switch to the + // hydration lane. + resetWorkInProgressStack(); + workInProgressRootExitStatus = RootDidNotComplete; + break outer; + } - if (nearestMountedAncestor !== null) { - abortParentMarkerTransitionsForDeletedFiber( - nearestMountedAncestor, - abortReason, - transitions, - instance, - false - ); + case SuspendedOnImmediate: + case SuspendedOnData: { + if (!didSuspendInShell && getSuspenseHandler() === null) { + didSuspendInShell = true; + } // Intentional fallthrough + } + + default: { + // Unwind then continue with the normal work loop. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + throwAndUnwindWorkLoop(unitOfWork, thrownValue); + break; + } } } - } - } - break; - } + workLoopSync(); + break; + } catch (thrownValue) { + handleThrow(root, thrownValue); + } + } while (true); // Check if something suspended in the shell. We use this to detect an + // infinite ping loop caused by an uncached promise. + // + // Only increment this counter once per synchronous render attempt across the + // whole tree. Even if there are many sibling components that suspend, this + // counter only gets incremented once. - case CacheComponent: { - { - var _cache = current.memoizedState.cache; - releaseCache(_cache); + if (didSuspendInShell) { + root.shellSuspendCounter++; } - break; - } - - case TracingMarkerComponent: { - if (enableTransitionTracing) { - // We need to mark this fiber's parents as deleted - var _instance5 = current.stateNode; - var _transitions = _instance5.transitions; - - if (_transitions !== null) { - var _abortReason = { - reason: "marker", - name: current.memoizedProps.name - }; - abortParentMarkerTransitionsForDeletedFiber( - current, - _abortReason, - _transitions, - null, - true - ); + resetContextDependencies(); + executionContext = prevExecutionContext; + popDispatcher(prevDispatcher); + popCacheDispatcher(prevCacheDispatcher); - if (nearestMountedAncestor !== null) { - abortParentMarkerTransitionsForDeletedFiber( - nearestMountedAncestor, - _abortReason, - _transitions, - null, - false - ); - } - } + if (workInProgress !== null) { + // This is a sync render, so we should have finished the whole tree. + throw new Error( + "Cannot commit an incomplete root. This error is likely caused by a " + + "bug in React. Please file an issue." + ); } - break; - } - } -} - -function invokeLayoutEffectMountInDEV(fiber) { - { - // We don't need to re-check StrictEffectsMode here. - // This function is only called if that check has already passed. - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - try { - commitHookEffectListMount(Layout | HasEffect, fiber); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); + { + if (enableDebugTracing) { + logRenderStopped(); } - - break; } - case ClassComponent: { - var instance = fiber.stateNode; - - if (typeof instance.componentDidMount === "function") { - try { - instance.componentDidMount(); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } - } - - break; - } - } - } -} + if (enableSchedulingProfiler) { + markRenderStopped(); + } // Set this to null to indicate there's no in-progress render. -function invokePassiveEffectMountInDEV(fiber) { - { - // We don't need to re-check StrictEffectsMode here. - // This function is only called if that check has already passed. - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - try { - commitHookEffectListMount(Passive | HasEffect, fiber); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } + workInProgressRoot = null; + workInProgressRootRenderLanes = NoLanes; // It's safe to process the queue now that the render phase is complete. - break; - } - } - } -} + finishQueueingConcurrentUpdates(); + return workInProgressRootExitStatus; + } // The work loop is an extremely hot path. Tell Closure not to inline it. -function invokeLayoutEffectUnmountInDEV(fiber) { - { - // We don't need to re-check StrictEffectsMode here. - // This function is only called if that check has already passed. - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - try { - commitHookEffectListUnmount(Layout | HasEffect, fiber, fiber.return); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } + /** @noinline */ - break; + function workLoopSync() { + // Perform work without checking if we need to yield between fiber. + while (workInProgress !== null) { + performUnitOfWork(workInProgress); } + } - case ClassComponent: { - var instance = fiber.stateNode; + function renderRootConcurrent(root, lanes) { + var prevExecutionContext = executionContext; + executionContext |= RenderContext; + var prevDispatcher = pushDispatcher(); + var prevCacheDispatcher = pushCacheDispatcher(); // If the root or lanes have changed, throw out the existing stack + // and prepare a fresh one. Otherwise we'll continue where we left off. - if (typeof instance.componentWillUnmount === "function") { - safelyCallComponentWillUnmount(fiber, fiber.return, instance); + if ( + workInProgressRoot !== root || + workInProgressRootRenderLanes !== lanes + ) { + { + if (isDevToolsPresent) { + var memoizedUpdaters = root.memoizedUpdaters; + + if (memoizedUpdaters.size > 0) { + restorePendingUpdaters(root, workInProgressRootRenderLanes); + memoizedUpdaters.clear(); + } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set. + // If we bailout on this work, we'll move them back (like above). + // It's important to move them now in case the work spawns more work at the same priority with different updaters. + // That way we can keep the current update and future updates separate. + + movePendingFibersToMemoized(root, lanes); + } } - break; + workInProgressTransitions = getTransitionsForLanes(root, lanes); + resetRenderTimer(); + prepareFreshStack(root, lanes); } - } - } -} -function invokePassiveEffectUnmountInDEV(fiber) { - { - // We don't need to re-check StrictEffectsMode here. - // This function is only called if that check has already passed. - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - try { - commitHookEffectListUnmount(Passive | HasEffect, fiber, fiber.return); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); + { + if (enableDebugTracing) { + logRenderStarted(lanes); } } - } - } -} -function getCacheSignal() { - var cache = readContext(CacheContext); - return cache.controller.signal; -} - -function getCacheForType(resourceType) { - var cache = readContext(CacheContext); - var cacheForType = cache.data.get(resourceType); + if (enableSchedulingProfiler) { + markRenderStarted(lanes); + } - if (cacheForType === undefined) { - cacheForType = resourceType(); - cache.data.set(resourceType, cacheForType); - } + outer: do { + try { + if ( + workInProgressSuspendedReason !== NotSuspended && + workInProgress !== null + ) { + // The work loop is suspended. We need to either unwind the stack or + // replay the suspended component. + var unitOfWork = workInProgress; + var thrownValue = workInProgressThrownValue; + + resumeOrUnwind: switch (workInProgressSuspendedReason) { + case SuspendedOnError: { + // Unwind then continue with the normal work loop. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + throwAndUnwindWorkLoop(unitOfWork, thrownValue); + break; + } - return cacheForType; -} + case SuspendedOnData: { + var thenable = thrownValue; -var DefaultCacheDispatcher = { - getCacheSignal: getCacheSignal, - getCacheForType: getCacheForType -}; - -if (typeof Symbol === "function" && Symbol.for) { - var symbolFor = Symbol.for; - symbolFor("selector.component"); - symbolFor("selector.has_pseudo_class"); - symbolFor("selector.role"); - symbolFor("selector.test_id"); - symbolFor("selector.text"); -} + if (isThenableResolved(thenable)) { + // The data resolved. Try rendering the component again. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + replaySuspendedUnitOfWork(unitOfWork); + break; + } // The work loop is suspended on data. We should wait for it to + // resolve before continuing to render. + // TODO: Handle the case where the promise resolves synchronously. + // Usually this is handled when we instrument the promise to add a + // `status` field, but if the promise already has a status, we won't + // have added a listener until right here. + + var onResolution = function () { + // Check if the root is still suspended on this promise. + if ( + workInProgressSuspendedReason === SuspendedOnData && + workInProgressRoot === root + ) { + // Mark the root as ready to continue rendering. + workInProgressSuspendedReason = SuspendedAndReadyToContinue; + } // Ensure the root is scheduled. We should do this even if we're + // currently working on a different root, so that we resume + // rendering later. + + ensureRootIsScheduled(root); + }; + + thenable.then(onResolution, onResolution); + break outer; + } -var ReactCurrentActQueue$1 = ReactSharedInternals.ReactCurrentActQueue; -function isLegacyActEnvironment(fiber) { - { - // Legacy mode. We preserve the behavior of React 17's act. It assumes an - // act environment whenever `jest` is defined, but you can still turn off - // spurious warnings by setting IS_REACT_ACT_ENVIRONMENT explicitly - // to false. - // $FlowFixMe[cannot-resolve-name] Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global - typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" // $FlowFixMe[cannot-resolve-name] - ? IS_REACT_ACT_ENVIRONMENT - : undefined; // $FlowFixMe[cannot-resolve-name] - Flow doesn't know about jest - return warnsIfNotActing; - } -} -function isConcurrentActEnvironment() { - { - var isReactActEnvironmentGlobal = // $FlowFixMe[cannot-resolve-name] Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global - typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" // $FlowFixMe[cannot-resolve-name] - ? IS_REACT_ACT_ENVIRONMENT - : undefined; + case SuspendedOnImmediate: { + // If this fiber just suspended, it's possible the data is already + // cached. Yield to the main thread to give it a chance to ping. If + // it does, we can retry immediately without unwinding the stack. + workInProgressSuspendedReason = SuspendedAndReadyToContinue; + break outer; + } - if ( - !isReactActEnvironmentGlobal && - ReactCurrentActQueue$1.current !== null - ) { - // TODO: Include link to relevant documentation page. - error( - "The current testing environment is not configured to support " + - "act(...)" - ); - } + case SuspendedOnInstance: { + workInProgressSuspendedReason = + SuspendedOnInstanceAndReadyToContinue; + break outer; + } - return isReactActEnvironmentGlobal; - } -} + case SuspendedAndReadyToContinue: { + var _thenable = thrownValue; -var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; -var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, - ReactCurrentCache = ReactSharedInternals.ReactCurrentCache, - ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner, - ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig, - ReactCurrentActQueue = ReactSharedInternals.ReactCurrentActQueue; -var NoContext = - /* */ - 0; -var BatchedContext = - /* */ - 1; -var RenderContext = - /* */ - 2; -var CommitContext = - /* */ - 4; -var RootInProgress = 0; -var RootFatalErrored = 1; -var RootErrored = 2; -var RootSuspended = 3; -var RootSuspendedWithDelay = 4; -var RootCompleted = 5; -var RootDidNotComplete = 6; // Describes where we are in the React execution stack - -var executionContext = NoContext; // The root we're working on - -var workInProgressRoot = null; // The fiber we're working on - -var workInProgress = null; // The lanes we're rendering - -var workInProgressRootRenderLanes = NoLanes; -var NotSuspended = 0; -var SuspendedOnError = 1; -var SuspendedOnData = 2; -var SuspendedOnImmediate = 3; -var SuspendedOnInstance = 4; -var SuspendedOnInstanceAndReadyToContinue = 5; -var SuspendedOnDeprecatedThrowPromise = 6; -var SuspendedAndReadyToContinue = 7; -var SuspendedOnHydration = 8; // When this is true, the work-in-progress fiber just suspended (or errored) and -// we've yet to unwind the stack. In some cases, we may yield to the main thread -// after this happens. If the fiber is pinged before we resume, we can retry -// immediately instead of unwinding the stack. - -var workInProgressSuspendedReason = NotSuspended; -var workInProgressThrownValue = null; // Whether a ping listener was attached during this render. This is slightly -// different that whether something suspended, because we don't add multiple -// listeners to a promise we've already seen (per root and lane). - -var workInProgressRootDidAttachPingListener = false; // A contextual version of workInProgressRootRenderLanes. It is a superset of -// the lanes that we started working on at the root. When we enter a subtree -// that is currently hidden, we add the lanes that would have committed if -// the hidden tree hadn't been deferred. This is modified by the -// HiddenContext module. -// -// Most things in the work loop should deal with workInProgressRootRenderLanes. -// Most things in begin/complete phases should deal with entangledRenderLanes. - -var entangledRenderLanes = NoLanes; // Whether to root completed, errored, suspended, etc. - -var workInProgressRootExitStatus = RootInProgress; // A fatal error, if one is thrown - -var workInProgressRootFatalError = null; // The work left over by components that were visited during this render. Only -// includes unprocessed updates, not work in bailed out children. - -var workInProgressRootSkippedLanes = NoLanes; // Lanes that were updated (in an interleaved event) during this render. - -var workInProgressRootInterleavedUpdatedLanes = NoLanes; // Lanes that were updated during the render phase (*not* an interleaved event). - -var workInProgressRootPingedLanes = NoLanes; // If this lane scheduled deferred work, this is the lane of the deferred task. - -var workInProgressDeferredLane = NoLane; // Errors that are thrown during the render phase. - -var workInProgressRootConcurrentErrors = null; // These are errors that we recovered from without surfacing them to the UI. -// We will log them once the tree commits. - -var workInProgressRootRecoverableErrors = null; // The most recent time we either committed a fallback, or when a fallback was -// filled in with the resolved UI. This lets us throttle the appearance of new -// content as it streams in, to minimize jank. -// TODO: Think of a better name for this variable? - -var globalMostRecentFallbackTime = 0; -var FALLBACK_THROTTLE_MS = 300; // The absolute time for when we should start giving up on rendering -// more and prefer CPU suspense heuristics instead. - -var workInProgressRootRenderTargetTime = Infinity; // How long a render is supposed to take before we start following CPU -// suspense heuristics and opt out of rendering more content. - -var RENDER_TIMEOUT_MS = 500; -var workInProgressTransitions = null; -function getWorkInProgressTransitions() { - return workInProgressTransitions; -} -var currentPendingTransitionCallbacks = null; -var currentEndTime = null; -function addTransitionStartCallbackToPendingTransition(transition) { - if (enableTransitionTracing) { - if (currentPendingTransitionCallbacks === null) { - currentPendingTransitionCallbacks = { - transitionStart: [], - transitionProgress: null, - transitionComplete: null, - markerProgress: null, - markerIncomplete: null, - markerComplete: null - }; - } + if (isThenableResolved(_thenable)) { + // The data resolved. Try rendering the component again. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + replaySuspendedUnitOfWork(unitOfWork); + } else { + // Otherwise, unwind then continue with the normal work loop. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + throwAndUnwindWorkLoop(unitOfWork, thrownValue); + } - if (currentPendingTransitionCallbacks.transitionStart === null) { - currentPendingTransitionCallbacks.transitionStart = []; - } + break; + } - currentPendingTransitionCallbacks.transitionStart.push(transition); - } -} -function addMarkerProgressCallbackToPendingTransition( - markerName, - transitions, - pendingBoundaries -) { - if (enableTransitionTracing) { - if (currentPendingTransitionCallbacks === null) { - currentPendingTransitionCallbacks = { - transitionStart: null, - transitionProgress: null, - transitionComplete: null, - markerProgress: new Map(), - markerIncomplete: null, - markerComplete: null - }; - } + case SuspendedOnInstanceAndReadyToContinue: { + switch (workInProgress.tag) { + case HostComponent: + case HostHoistable: + case HostSingleton: { + // Before unwinding the stack, check one more time if the + // instance is ready. It may have loaded when React yielded to + // the main thread. + // Assigning this to a constant so Flow knows the binding won't + // be mutated by `preloadInstance`. + var hostFiber = workInProgress; + var type = hostFiber.type; + var props = hostFiber.pendingProps; + var isReady = preloadInstance(type, props); + + if (isReady) { + // The data resolved. Resume the work loop as if nothing + // suspended. Unlike when a user component suspends, we don't + // have to replay anything because the host fiber + // already completed. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + var sibling = hostFiber.sibling; + + if (sibling !== null) { + workInProgress = sibling; + } else { + var returnFiber = hostFiber.return; + + if (returnFiber !== null) { + workInProgress = returnFiber; + completeUnitOfWork(returnFiber); + } else { + workInProgress = null; + } + } + + break resumeOrUnwind; + } - if (currentPendingTransitionCallbacks.markerProgress === null) { - currentPendingTransitionCallbacks.markerProgress = new Map(); - } + break; + } - currentPendingTransitionCallbacks.markerProgress.set(markerName, { - pendingBoundaries: pendingBoundaries, - transitions: transitions - }); - } -} -function addMarkerIncompleteCallbackToPendingTransition( - markerName, - transitions, - aborts -) { - if (enableTransitionTracing) { - if (currentPendingTransitionCallbacks === null) { - currentPendingTransitionCallbacks = { - transitionStart: null, - transitionProgress: null, - transitionComplete: null, - markerProgress: null, - markerIncomplete: new Map(), - markerComplete: null - }; - } + default: { + // This will fail gracefully but it's not correct, so log a + // warning in dev. + if (true) { + error( + "Unexpected type of fiber triggered a suspensey commit. " + + "This is a bug in React." + ); + } - if (currentPendingTransitionCallbacks.markerIncomplete === null) { - currentPendingTransitionCallbacks.markerIncomplete = new Map(); - } + break; + } + } // Otherwise, unwind then continue with the normal work loop. - currentPendingTransitionCallbacks.markerIncomplete.set(markerName, { - transitions: transitions, - aborts: aborts - }); - } -} -function addMarkerCompleteCallbackToPendingTransition(markerName, transitions) { - if (enableTransitionTracing) { - if (currentPendingTransitionCallbacks === null) { - currentPendingTransitionCallbacks = { - transitionStart: null, - transitionProgress: null, - transitionComplete: null, - markerProgress: null, - markerIncomplete: null, - markerComplete: new Map() - }; - } + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + throwAndUnwindWorkLoop(unitOfWork, thrownValue); + break; + } - if (currentPendingTransitionCallbacks.markerComplete === null) { - currentPendingTransitionCallbacks.markerComplete = new Map(); - } + case SuspendedOnDeprecatedThrowPromise: { + // Suspended by an old implementation that uses the `throw promise` + // pattern. The newer replaying behavior can cause subtle issues + // like infinite ping loops. So we maintain the old behavior and + // always unwind. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + throwAndUnwindWorkLoop(unitOfWork, thrownValue); + break; + } - currentPendingTransitionCallbacks.markerComplete.set( - markerName, - transitions - ); - } -} -function addTransitionProgressCallbackToPendingTransition( - transition, - boundaries -) { - if (enableTransitionTracing) { - if (currentPendingTransitionCallbacks === null) { - currentPendingTransitionCallbacks = { - transitionStart: null, - transitionProgress: new Map(), - transitionComplete: null, - markerProgress: null, - markerIncomplete: null, - markerComplete: null - }; - } + case SuspendedOnHydration: { + // Selective hydration. An update flowed into a dehydrated tree. + // Interrupt the current render so the work loop can switch to the + // hydration lane. + resetWorkInProgressStack(); + workInProgressRootExitStatus = RootDidNotComplete; + break outer; + } - if (currentPendingTransitionCallbacks.transitionProgress === null) { - currentPendingTransitionCallbacks.transitionProgress = new Map(); - } + default: { + throw new Error( + "Unexpected SuspendedReason. This is a bug in React." + ); + } + } + } - currentPendingTransitionCallbacks.transitionProgress.set( - transition, - boundaries - ); - } -} -function addTransitionCompleteCallbackToPendingTransition(transition) { - if (enableTransitionTracing) { - if (currentPendingTransitionCallbacks === null) { - currentPendingTransitionCallbacks = { - transitionStart: null, - transitionProgress: null, - transitionComplete: [], - markerProgress: null, - markerIncomplete: null, - markerComplete: null - }; - } + if (true && ReactCurrentActQueue.current !== null) { + // `act` special case: If we're inside an `act` scope, don't consult + // `shouldYield`. Always keep working until the render is complete. + // This is not just an optimization: in a unit test environment, we + // can't trust the result of `shouldYield`, because the host I/O is + // likely mocked. + workLoopSync(); + } else { + workLoopConcurrent(); + } - if (currentPendingTransitionCallbacks.transitionComplete === null) { - currentPendingTransitionCallbacks.transitionComplete = []; - } + break; + } catch (thrownValue) { + handleThrow(root, thrownValue); + } + } while (true); - currentPendingTransitionCallbacks.transitionComplete.push(transition); - } -} + resetContextDependencies(); + popDispatcher(prevDispatcher); + popCacheDispatcher(prevCacheDispatcher); + executionContext = prevExecutionContext; -function resetRenderTimer() { - workInProgressRootRenderTargetTime = now$1() + RENDER_TIMEOUT_MS; -} + { + if (enableDebugTracing) { + logRenderStopped(); + } + } // Check if the tree has completed. -function getRenderTargetTime() { - return workInProgressRootRenderTargetTime; -} -var hasUncaughtError = false; -var firstUncaughtError = null; -var legacyErrorBoundariesThatAlreadyFailed = null; // Only used when enableProfilerNestedUpdateScheduledHook is true; -// to track which root is currently committing layout effects. - -var rootCommittingMutationOrLayoutEffects = null; -var rootDoesHavePassiveEffects = false; -var rootWithPendingPassiveEffects = null; -var pendingPassiveEffectsLanes = NoLanes; -var pendingPassiveProfilerEffects = []; -var pendingPassiveEffectsRemainingLanes = NoLanes; -var pendingPassiveTransitions = null; // Use these to prevent an infinite loop of nested updates - -var NESTED_UPDATE_LIMIT = 50; -var nestedUpdateCount = 0; -var rootWithNestedUpdates = null; -var isFlushingPassiveEffects = false; -var didScheduleUpdateDuringPassiveEffects = false; -var NESTED_PASSIVE_UPDATE_LIMIT = 50; -var nestedPassiveUpdateCount = 0; -var rootWithPassiveNestedUpdates = null; -var isRunningInsertionEffect = false; -function getWorkInProgressRoot() { - return workInProgressRoot; -} -function getWorkInProgressRootRenderLanes() { - return workInProgressRootRenderLanes; -} -function isWorkLoopSuspendedOnData() { - return workInProgressSuspendedReason === SuspendedOnData; -} -function requestUpdateLane(fiber) { - // Special cases - var mode = fiber.mode; - - if ((mode & ConcurrentMode) === NoMode) { - return SyncLane; - } else if ( - (executionContext & RenderContext) !== NoContext && - workInProgressRootRenderLanes !== NoLanes - ) { - // This is a render phase update. These are not officially supported. The - // old behavior is to give this the same "thread" (lanes) as - // whatever is currently rendering. So if you call `setState` on a component - // that happens later in the same render, it will flush. Ideally, we want to - // remove the special case and treat them as if they came from an - // interleaved event. Regardless, this pattern is not officially supported. - // This behavior is only a fallback. The flag only exists until we can roll - // out the setState warning, since existing code might accidentally rely on - // the current behavior. - return pickArbitraryLane(workInProgressRootRenderLanes); - } - - var isTransition = requestCurrentTransition() !== NoTransition; - - if (isTransition) { - if (ReactCurrentBatchConfig.transition !== null) { - var transition = ReactCurrentBatchConfig.transition; - - if (!transition._updatedFibers) { - transition._updatedFibers = new Set(); - } - - transition._updatedFibers.add(fiber); - } - - var actionScopeLane = peekEntangledActionLane(); - return actionScopeLane !== NoLane // We're inside an async action scope. Reuse the same lane. - ? actionScopeLane // We may or may not be inside an async action scope. If we are, this - : // is the first update in that scope. Either way, we need to get a - // fresh transition lane. - requestTransitionLane(); - } // Updates originating inside certain React methods, like flushSync, have - // their priority set by tracking it with a context variable. - // - // The opaque type returned by the host config is internally a lane, so we can - // use that directly. - // TODO: Move this type conversion to the event priority module. - - var updateLane = getCurrentUpdatePriority(); - - if (updateLane !== NoLane) { - return updateLane; - } // This update originated outside React. Ask the host environment for an - // appropriate priority, based on the type of event. - // - // The opaque type returned by the host config is internally a lane, so we can - // use that directly. - // TODO: Move this type conversion to the event priority module. - - var eventLane = getCurrentEventPriority(); - return eventLane; -} + if (workInProgress !== null) { + // Still work remaining. + if (enableSchedulingProfiler) { + markRenderYielded(); + } -function requestRetryLane(fiber) { - // This is a fork of `requestUpdateLane` designed specifically for Suspense - // "retries" — a special update that attempts to flip a Suspense boundary - // from its placeholder state to its primary/resolved state. - // Special cases - var mode = fiber.mode; + return RootInProgress; + } else { + // Completed the tree. + if (enableSchedulingProfiler) { + markRenderStopped(); + } // Set this to null to indicate there's no in-progress render. - if ((mode & ConcurrentMode) === NoMode) { - return SyncLane; - } + workInProgressRoot = null; + workInProgressRootRenderLanes = NoLanes; // It's safe to process the queue now that the render phase is complete. - return claimNextRetryLane(); -} + finishQueueingConcurrentUpdates(); // Return the final exit status. -function requestDeferredLane() { - if (workInProgressDeferredLane === NoLane) { - // If there are multiple useDeferredValue hooks in the same render, the - // tasks that they spawn should all be batched together, so they should all - // receive the same lane. - // Check the priority of the current render to decide the priority of the - // deferred task. - // OffscreenLane is used for prerendering, but we also use OffscreenLane - // for incremental hydration. It's given the lowest priority because the - // initial HTML is the same as the final UI. But useDeferredValue during - // hydration is an exception — we need to upgrade the UI to the final - // value. So if we're currently hydrating, we treat it like a transition. - var isPrerendering = - includesSomeLane(workInProgressRootRenderLanes, OffscreenLane) && - !getIsHydrating(); - - if (isPrerendering) { - // There's only one OffscreenLane, so if it contains deferred work, we - // should just reschedule using the same lane. - workInProgressDeferredLane = OffscreenLane; - } else { - // Everything else is spawned as a transition. - workInProgressDeferredLane = requestTransitionLane(); + return workInProgressRootExitStatus; + } } - } + /** @noinline */ - return workInProgressDeferredLane; -} -function scheduleUpdateOnFiber(root, fiber, lane) { - { - if (isRunningInsertionEffect) { - error("useInsertionEffect must not schedule updates."); - } - } - - { - if (isFlushingPassiveEffects) { - didScheduleUpdateDuringPassiveEffects = true; - } - } // Check if the work loop is currently suspended and waiting for data to - // finish loading. - - if ( - // Suspended render phase - (root === workInProgressRoot && - workInProgressSuspendedReason === SuspendedOnData) || // Suspended commit phase - root.cancelPendingCommit !== null - ) { - // The incoming update might unblock the current render. Interrupt the - // current attempt and restart from the top. - prepareFreshStack(root, NoLanes); - markRootSuspended( - root, - workInProgressRootRenderLanes, - workInProgressDeferredLane - ); - } // Mark that the root has a pending update. - - markRootUpdated(root, lane); - - if ( - (executionContext & RenderContext) !== NoLanes && - root === workInProgressRoot - ) { - // This update was dispatched during the render phase. This is a mistake - // if the update originates from user space (with the exception of local - // hook updates, which are handled differently and don't reach this - // function), but there are some internal React features that use this as - // an implementation detail, like selective hydration. - warnAboutRenderPhaseUpdatesInDEV(fiber); // Track lanes that were updated during the render phase - } else { - // This is a normal update, scheduled from outside the render phase. For - // example, during an input event. - { - if (isDevToolsPresent) { - addFiberToLanesMap(root, fiber, lane); + function workLoopConcurrent() { + // Perform work until Scheduler asks us to yield + while (workInProgress !== null && !shouldYield()) { + // $FlowFixMe[incompatible-call] found when upgrading Flow + performUnitOfWork(workInProgress); } } - warnIfUpdatesNotWrappedWithActDEV(fiber); - - if (enableProfilerNestedUpdateScheduledHook) { - if ( - (executionContext & CommitContext) !== NoContext && - root === rootCommittingMutationOrLayoutEffects - ) { - if (fiber.mode & ProfileMode) { - var current = fiber; - - while (current !== null) { - if (current.tag === Profiler) { - var _current$memoizedProp = current.memoizedProps, - id = _current$memoizedProp.id, - onNestedUpdateScheduled = - _current$memoizedProp.onNestedUpdateScheduled; - - if (typeof onNestedUpdateScheduled === "function") { - onNestedUpdateScheduled(id); - } - } + function performUnitOfWork(unitOfWork) { + // The current, flushed, state of this fiber is the alternate. Ideally + // nothing should rely on this, but relying on it here means that we don't + // need an additional field on the work in progress. + var current = unitOfWork.alternate; + setCurrentFiber(unitOfWork); + var next; - current = current.return; - } - } + if ((unitOfWork.mode & ProfileMode) !== NoMode) { + startProfilerTimer(unitOfWork); + next = beginWork(current, unitOfWork, entangledRenderLanes); + stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); + } else { + next = beginWork(current, unitOfWork, entangledRenderLanes); } - } - - if (enableTransitionTracing) { - var transition = ReactCurrentBatchConfig.transition; - if (transition !== null && transition.name != null) { - if (transition.startTime === -1) { - transition.startTime = now$1(); - } + resetCurrentFiber(); + unitOfWork.memoizedProps = unitOfWork.pendingProps; - addTransitionToLanesMap(root, transition, lane); + if (next === null) { + // If this doesn't spawn new work, complete the current work. + completeUnitOfWork(unitOfWork); + } else { + workInProgress = next; } + + ReactCurrentOwner.current = null; } - if (root === workInProgressRoot) { - // Received an update to a tree that's in the middle of rendering. Mark - // that there was an interleaved update work on this root. - if ((executionContext & RenderContext) === NoContext) { - workInProgressRootInterleavedUpdatedLanes = mergeLanes( - workInProgressRootInterleavedUpdatedLanes, - lane - ); - } + function replaySuspendedUnitOfWork(unitOfWork) { + // This is a fork of performUnitOfWork specifcally for replaying a fiber that + // just suspended. + // + var current = unitOfWork.alternate; + setCurrentFiber(unitOfWork); + var next; + setCurrentFiber(unitOfWork); + var isProfilingMode = (unitOfWork.mode & ProfileMode) !== NoMode; - if (workInProgressRootExitStatus === RootSuspendedWithDelay) { - // The root already suspended with a delay, which means this render - // definitely won't finish. Since we have a new update, let's mark it as - // suspended now, right before marking the incoming update. This has the - // effect of interrupting the current render and switching to the update. - // TODO: Make sure this doesn't override pings that happen while we've - // already started rendering. - markRootSuspended( - root, - workInProgressRootRenderLanes, - workInProgressDeferredLane - ); + if (isProfilingMode) { + startProfilerTimer(unitOfWork); } - } - ensureRootIsScheduled(root); + switch (unitOfWork.tag) { + case IndeterminateComponent: { + // Because it suspended with `use`, we can assume it's a + // function component. + unitOfWork.tag = FunctionComponent; // Fallthrough to the next branch. + } - if ( - lane === SyncLane && - executionContext === NoContext && - (fiber.mode & ConcurrentMode) === NoMode - ) { - if (ReactCurrentActQueue.isBatchingLegacy); - else { - // Flush the synchronous work now, unless we're already working or inside - // a batch. This is intentionally inside scheduleUpdateOnFiber instead of - // scheduleCallbackForFiber to preserve the ability to schedule a callback - // without immediately flushing it. We only do this for user-initiated - // updates, to preserve historical behavior of legacy mode. - resetRenderTimer(); - flushSyncWorkOnLegacyRootsOnly(); - } - } - } -} -function isUnsafeClassRenderPhaseUpdate(fiber) { - // Check if this is a render phase update. Only called by class components, - // which special (deprecated) behavior for UNSAFE_componentWillReceive props. - return (executionContext & RenderContext) !== NoContext; -} // This is the entry point for every concurrent task, i.e. anything that -// goes through Scheduler. - -function performConcurrentWorkOnRoot(root, didTimeout) { - { - resetNestedUpdateFlag(); - } - - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - throw new Error("Should not already be working."); - } // Flush any pending passive effects before deciding which lanes to work on, - // in case they schedule additional work. - - var originalCallbackNode = root.callbackNode; - var didFlushPassiveEffects = flushPassiveEffects(); - - if (didFlushPassiveEffects) { - // Something in the passive effect phase may have canceled the current task. - // Check if the task node for this root was changed. - if (root.callbackNode !== originalCallbackNode) { - // The current task was canceled. Exit. We don't need to call - // `ensureRootIsScheduled` because the check above implies either that - // there's a new task, or that there's no remaining work on this root. - return null; - } - } // Determine the next lanes to work on, using the fields stored - // on the root. - // TODO: This was already computed in the caller. Pass it as an argument. - - var lanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes - ); - - if (lanes === NoLanes) { - // Defensive coding. This is never expected to happen. - return null; - } // We disable time-slicing in some cases: if the work has been CPU-bound - // for too long ("expired" work, to prevent starvation), or we're in - // sync-updates-by-default mode. - // TODO: We only check `didTimeout` defensively, to account for a Scheduler - // bug we're still investigating. Once the bug in Scheduler is fixed, - // we can remove this, since we track expiration ourselves. - - var shouldTimeSlice = - !includesBlockingLane(root, lanes) && - !includesExpiredLane(root, lanes) && - (disableSchedulerTimeoutInWorkLoop || !didTimeout); - var exitStatus = shouldTimeSlice - ? renderRootConcurrent(root, lanes) - : renderRootSync(root, lanes); - - if (exitStatus !== RootInProgress) { - var renderWasConcurrent = shouldTimeSlice; - - do { - if (exitStatus === RootDidNotComplete) { - // The render unwound without completing the tree. This happens in special - // cases where need to exit the current render without producing a - // consistent tree or committing. - markRootSuspended(root, lanes, NoLane); - } else { - // The render completed. - // Check if this render may have yielded to a concurrent event, and if so, - // confirm that any newly rendered stores are consistent. - // TODO: It's possible that even a concurrent render may never have yielded - // to the main thread, if it was fast enough, or if it expired. We could - // skip the consistency check in that case, too. - var finishedWork = root.current.alternate; + case SimpleMemoComponent: + case FunctionComponent: { + // Resolve `defaultProps`. This logic is copied from `beginWork`. + // TODO: Consider moving this switch statement into that module. Also, + // could maybe use this as an opportunity to say `use` doesn't work with + // `defaultProps` :) + var Component = unitOfWork.type; + var unresolvedProps = unitOfWork.pendingProps; + var resolvedProps = + unitOfWork.elementType === Component + ? unresolvedProps + : resolveDefaultProps(Component, unresolvedProps); + var context; - if ( - renderWasConcurrent && - !isRenderConsistentWithExternalStores(finishedWork) - ) { - // A store was mutated in an interleaved event. Render again, - // synchronously, to block further mutations. - exitStatus = renderRootSync(root, lanes); // We assume the tree is now consistent because we didn't yield to any - // concurrent events. + { + var unmaskedContext = getUnmaskedContext( + unitOfWork, + Component, + true + ); + context = getMaskedContext(unitOfWork, unmaskedContext); + } - renderWasConcurrent = false; // Need to check the exit status again. + next = replayFunctionComponent( + current, + unitOfWork, + resolvedProps, + Component, + context, + workInProgressRootRenderLanes + ); + break; + } - continue; - } // Check if something threw + case ForwardRef: { + // Resolve `defaultProps`. This logic is copied from `beginWork`. + // TODO: Consider moving this switch statement into that module. Also, + // could maybe use this as an opportunity to say `use` doesn't work with + // `defaultProps` :) + var _Component = unitOfWork.type.render; + var _unresolvedProps = unitOfWork.pendingProps; - if (exitStatus === RootErrored) { - var originallyAttemptedLanes = lanes; - var errorRetryLanes = getLanesToRetrySynchronouslyOnError( - root, - originallyAttemptedLanes + var _resolvedProps = + unitOfWork.elementType === _Component + ? _unresolvedProps + : resolveDefaultProps(_Component, _unresolvedProps); + + next = replayFunctionComponent( + current, + unitOfWork, + _resolvedProps, + _Component, + unitOfWork.ref, + workInProgressRootRenderLanes ); + break; + } - if (errorRetryLanes !== NoLanes) { - lanes = errorRetryLanes; - exitStatus = recoverFromConcurrentError( - root, - originallyAttemptedLanes, - errorRetryLanes - ); - renderWasConcurrent = false; - } + case HostComponent: { + // Some host components are stateful (that's how we implement form + // actions) but we don't bother to reuse the memoized state because it's + // not worth the extra code. The main reason to reuse the previous hooks + // is to reuse uncached promises, but we happen to know that the only + // promises that a host component might suspend on are definitely cached + // because they are controlled by us. So don't bother. + resetHooksOnUnwind(unitOfWork); // Fallthrough to the next branch. + } + + default: { + // Other types besides function components are reset completely before + // being replayed. Currently this only happens when a Usable type is + // reconciled — the reconciler will suspend. + // + // We reset the fiber back to its original state; however, this isn't + // a full "unwind" because we're going to reuse the promises that were + // reconciled previously. So it's intentional that we don't call + // resetSuspendedWorkLoopOnUnwind here. + unwindInterruptedWork(current, unitOfWork); + unitOfWork = workInProgress = resetWorkInProgress( + unitOfWork, + entangledRenderLanes + ); + next = beginWork(current, unitOfWork, entangledRenderLanes); + break; } + } + + if (isProfilingMode) { + stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); + } // The begin phase finished successfully without suspending. Return to the + // normal work loop. - if (exitStatus === RootFatalErrored) { - var fatalError = workInProgressRootFatalError; - prepareFreshStack(root, NoLanes); - markRootSuspended(root, lanes, NoLane); - ensureRootIsScheduled(root); - throw fatalError; - } // We now have a consistent tree. The next step is either to commit it, - // or, if something suspended, wait to commit it after a timeout. + resetCurrentFiber(); + unitOfWork.memoizedProps = unitOfWork.pendingProps; - root.finishedWork = finishedWork; - root.finishedLanes = lanes; - finishConcurrentRender(root, exitStatus, finishedWork, lanes); + if (next === null) { + // If this doesn't spawn new work, complete the current work. + completeUnitOfWork(unitOfWork); + } else { + workInProgress = next; } - break; - } while (true); - } + ReactCurrentOwner.current = null; + } - ensureRootIsScheduled(root); - return getContinuationForRoot(root, originalCallbackNode); -} + function throwAndUnwindWorkLoop(unitOfWork, thrownValue) { + // This is a fork of performUnitOfWork specifcally for unwinding a fiber + // that threw an exception. + // + // Return to the normal work loop. This will unwind the stack, and potentially + // result in showing a fallback. + resetSuspendedWorkLoopOnUnwind(unitOfWork); + var returnFiber = unitOfWork.return; + + if (returnFiber === null || workInProgressRoot === null) { + // Expected to be working on a non-root fiber. This is a fatal error + // because there's no ancestor that can handle it; the root is + // supposed to capture all errors that weren't caught by an error + // boundary. + workInProgressRootExitStatus = RootFatalErrored; + workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next + // sibling, or the parent if there are no siblings. But since the root + // has no siblings nor a parent, we set it to null. Usually this is + // handled by `completeUnitOfWork` or `unwindWork`, but since we're + // intentionally not calling those, we need set it here. + // TODO: Consider calling `unwindWork` to pop the contexts. + + workInProgress = null; + return; + } -function recoverFromConcurrentError( - root, - originallyAttemptedLanes, - errorRetryLanes -) { - // If an error occurred during hydration, discard server response and fall - // back to client side render. - // Before rendering again, save the errors from the previous attempt. - var errorsFromFirstAttempt = workInProgressRootConcurrentErrors; - var wasRootDehydrated = isRootDehydrated(root); - - if (wasRootDehydrated) { - // The shell failed to hydrate. Set a flag to force a client rendering - // during the next attempt. To do this, we call prepareFreshStack now - // to create the root work-in-progress fiber. This is a bit weird in terms - // of factoring, because it relies on renderRootSync not calling - // prepareFreshStack again in the call below, which happens because the - // root and lanes haven't changed. - // - // TODO: I think what we should do is set ForceClientRender inside - // throwException, like we do for nested Suspense boundaries. The reason - // it's here instead is so we can switch to the synchronous work loop, too. - // Something to consider for a future refactor. - var rootWorkInProgress = prepareFreshStack(root, errorRetryLanes); - rootWorkInProgress.flags |= ForceClientRender; + try { + // Find and mark the nearest Suspense or error boundary that can handle + // this "exception". + throwException( + workInProgressRoot, + returnFiber, + unitOfWork, + thrownValue, + workInProgressRootRenderLanes + ); + } catch (error) { + // We had trouble processing the error. An example of this happening is + // when accessing the `componentDidCatch` property of an error boundary + // throws an error. A weird edge case. There's a regression test for this. + // To prevent an infinite loop, bubble the error up to the next parent. + workInProgress = returnFiber; + throw error; + } - { - errorHydratingContainer(); + if (unitOfWork.flags & Incomplete) { + // Unwind the stack until we reach the nearest boundary. + unwindUnitOfWork(unitOfWork); + } else { + // Although the fiber suspended, we're intentionally going to commit it in + // an inconsistent state. We can do this safely in cases where we know the + // inconsistent tree will be hidden. + // + // This currently only applies to Legacy Suspense implementation, but we may + // port a version of this to concurrent roots, too, when performing a + // synchronous render. Because that will allow us to mutate the tree as we + // go instead of buffering mutations until the end. Though it's unclear if + // this particular path is how that would be implemented. + completeUnitOfWork(unitOfWork); + } } - } - var exitStatus = renderRootSync(root, errorRetryLanes); + function completeUnitOfWork(unitOfWork) { + // Attempt to complete the current unit of work, then move to the next + // sibling. If there are no more siblings, return to the parent fiber. + var completedWork = unitOfWork; - if (exitStatus !== RootErrored) { - // Successfully finished rendering on retry - if (workInProgressRootDidAttachPingListener && !wasRootDehydrated) { - // During the synchronous render, we attached additional ping listeners. - // This is highly suggestive of an uncached promise (though it's not the - // only reason this would happen). If it was an uncached promise, then - // it may have masked a downstream error from ocurring without actually - // fixing it. Example: - // - // use(Promise.resolve('uncached')) - // throw new Error('Oops!') - // - // When this happens, there's a conflict between blocking potential - // concurrent data races and unwrapping uncached promise values. We - // have to choose one or the other. Because the data race recovery is - // a last ditch effort, we'll disable it. - root.errorRecoveryDisabledLanes = mergeLanes( - root.errorRecoveryDisabledLanes, - originallyAttemptedLanes - ); // Mark the current render as suspended and force it to restart. Once - // these lanes finish successfully, we'll re-enable the error recovery - // mechanism for subsequent updates. - - workInProgressRootInterleavedUpdatedLanes |= originallyAttemptedLanes; - return RootSuspendedWithDelay; - } // The errors from the failed first attempt have been recovered. Add - // them to the collection of recoverable errors. We'll log them in the - // commit phase. - - var errorsFromSecondAttempt = workInProgressRootRecoverableErrors; - workInProgressRootRecoverableErrors = errorsFromFirstAttempt; // The errors from the second attempt should be queued after the errors - // from the first attempt, to preserve the causal sequence. - - if (errorsFromSecondAttempt !== null) { - queueRecoverableErrors(errorsFromSecondAttempt); - } - } - - return exitStatus; -} + do { + { + if ((completedWork.flags & Incomplete) !== NoFlags$1) { + // NOTE: If we re-enable sibling prerendering in some cases, this branch + // is where we would switch to the unwinding path. + error( + "Internal React error: Expected this fiber to be complete, but " + + "it isn't. It should have been unwound. This is a bug in React." + ); + } + } // The current, flushed, state of this fiber is the alternate. Ideally + // nothing should rely on this, but relying on it here means that we don't + // need an additional field on the work in progress. -function queueRecoverableErrors(errors) { - if (workInProgressRootRecoverableErrors === null) { - workInProgressRootRecoverableErrors = errors; - } else { - // $FlowFixMe[method-unbinding] - workInProgressRootRecoverableErrors.push.apply( - workInProgressRootRecoverableErrors, - errors - ); - } -} + var current = completedWork.alternate; + var returnFiber = completedWork.return; + setCurrentFiber(completedWork); + var next = void 0; -function finishConcurrentRender(root, exitStatus, finishedWork, lanes) { - // TODO: The fact that most of these branches are identical suggests that some - // of the exit statuses are not best modeled as exit statuses and should be - // tracked orthogonally. - switch (exitStatus) { - case RootInProgress: - case RootFatalErrored: { - throw new Error("Root did not complete. This is a bug in React."); - } - - case RootSuspendedWithDelay: { - if (includesOnlyTransitions(lanes)) { - // This is a transition, so we should exit without committing a - // placeholder and without scheduling a timeout. Delay indefinitely - // until we receive more data. - markRootSuspended(root, lanes, workInProgressDeferredLane); - return; - } // Commit the placeholder. + if ((completedWork.mode & ProfileMode) === NoMode) { + next = completeWork(current, completedWork, entangledRenderLanes); + } else { + startProfilerTimer(completedWork); + next = completeWork(current, completedWork, entangledRenderLanes); // Update render duration assuming we didn't error. - break; - } + stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); + } - case RootErrored: - case RootSuspended: - case RootCompleted: { - break; - } + resetCurrentFiber(); - default: { - throw new Error("Unknown root exit status."); - } - } + if (next !== null) { + // Completing this fiber spawned new work. Work on that next. + workInProgress = next; + return; + } - if (shouldForceFlushFallbacksInDEV()) { - // We're inside an `act` scope. Commit immediately. - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - workInProgressDeferredLane - ); - } else { - if ( - includesOnlyRetries(lanes) && - (alwaysThrottleRetries || exitStatus === RootSuspended) - ) { - // This render only included retries, no updates. Throttle committing - // retries so that we don't show too many loading states too quickly. - var msUntilTimeout = - globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now$1(); // Don't bother with a very short suspense time. - - if (msUntilTimeout > 10) { - markRootSuspended(root, lanes, workInProgressDeferredLane); - var nextLanes = getNextLanes(root, NoLanes); - - if (nextLanes !== NoLanes) { - // There's additional work we can do on this root. We might as well - // attempt to work on that while we're suspended. + var siblingFiber = completedWork.sibling; + + if (siblingFiber !== null) { + // If there is more work to do in this returnFiber, do that next. + workInProgress = siblingFiber; return; - } // The render is suspended, it hasn't timed out, and there's no - // lower priority work to do. Instead of committing the fallback - // immediately, wait for more data to arrive. - // TODO: Combine retry throttling with Suspensey commits. Right now they - // run one after the other. - - root.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( - null, - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes, - workInProgressDeferredLane - ), - msUntilTimeout - ); - return; + } // Otherwise, return to the parent + // $FlowFixMe[incompatible-type] we bail out when we get a null + + completedWork = returnFiber; // Update the next thing we're working on in case something throws. + + workInProgress = completedWork; + } while (completedWork !== null); // We've reached the root. + + if (workInProgressRootExitStatus === RootInProgress) { + workInProgressRootExitStatus = RootCompleted; } } - commitRootWhenReady( - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes, - workInProgressDeferredLane - ); - } -} + function unwindUnitOfWork(unitOfWork) { + var incompleteWork = unitOfWork; -function commitRootWhenReady( - root, - finishedWork, - recoverableErrors, - transitions, - lanes, - spawnedLane -) { - // TODO: Combine retry throttling with Suspensey commits. Right now they run - // one after the other. - if (includesOnlyNonUrgentLanes(lanes)) { - // the suspensey resources. The renderer is responsible for accumulating - // all the load events. This all happens in a single synchronous - // transaction, so it track state in its own module scope. - - accumulateSuspenseyCommit(finishedWork); // At the end, ask the renderer if it's ready to commit, or if we should - // suspend. If it's not ready, it will return a callback to subscribe to - // a ready event. - - var schedulePendingCommit = waitForCommitToBeReady(); - - if (schedulePendingCommit !== null) { - // NOTE: waitForCommitToBeReady returns a subscribe function so that we - // only allocate a function if the commit isn't ready yet. The other - // pattern would be to always pass a callback to waitForCommitToBeReady. - // Not yet ready to commit. Delay the commit until the renderer notifies - // us that it's ready. This will be canceled if we start work on the - // root again. - root.cancelPendingCommit = schedulePendingCommit( - commitRoot.bind(null, root, recoverableErrors, transitions) - ); - markRootSuspended(root, lanes, spawnedLane); - return; - } - } // Otherwise, commit immediately. + do { + // The current, flushed, state of this fiber is the alternate. Ideally + // nothing should rely on this, but relying on it here means that we don't + // need an additional field on the work in progress. + var current = incompleteWork.alternate; // This fiber did not complete because something threw. Pop values off + // the stack without entering the complete phase. If this is a boundary, + // capture values if possible. + + var next = unwindWork(current, incompleteWork); // Because this fiber did not complete, don't reset its lanes. + + if (next !== null) { + // Found a boundary that can handle this exception. Re-renter the + // begin phase. This branch will return us to the normal work loop. + // + // Since we're restarting, remove anything that is not a host effect + // from the effect tag. + next.flags &= HostEffectMask; + workInProgress = next; + return; + } // Keep unwinding until we reach either a boundary or the root. + + if ((incompleteWork.mode & ProfileMode) !== NoMode) { + // Record the render duration for the fiber that errored. + stopProfilerTimerIfRunningAndRecordDelta(incompleteWork, false); // Include the time spent working on failed children before continuing. - commitRoot(root, recoverableErrors, transitions, spawnedLane); -} + var actualDuration = incompleteWork.actualDuration; + var child = incompleteWork.child; -function isRenderConsistentWithExternalStores(finishedWork) { - // Search the rendered tree for external store reads, and check whether the - // stores were mutated in a concurrent event. Intentionally using an iterative - // loop instead of recursion so we can exit early. - var node = finishedWork; + while (child !== null) { + // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + actualDuration += child.actualDuration; + child = child.sibling; + } - while (true) { - if (node.flags & StoreConsistency) { - var updateQueue = node.updateQueue; + incompleteWork.actualDuration = actualDuration; + } // TODO: Once we stop prerendering siblings, instead of resetting the parent + // of the node being unwound, we should be able to reset node itself as we + // unwind the stack. Saves an additional null check. - if (updateQueue !== null) { - var checks = updateQueue.stores; + var returnFiber = incompleteWork.return; - if (checks !== null) { - for (var i = 0; i < checks.length; i++) { - var check = checks[i]; - var getSnapshot = check.getSnapshot; - var renderedValue = check.value; + if (returnFiber !== null) { + // Mark the parent fiber as incomplete and clear its subtree flags. + // TODO: Once we stop prerendering siblings, we may be able to get rid of + // the Incomplete flag because unwinding to the nearest boundary will + // happen synchronously. + returnFiber.flags |= Incomplete; + returnFiber.subtreeFlags = NoFlags$1; + returnFiber.deletions = null; + } // NOTE: If we re-enable sibling prerendering in some cases, here we + // would switch to the normal completion path: check if a sibling + // exists, and if so, begin work on it. + // Otherwise, return to the parent + // $FlowFixMe[incompatible-type] we bail out when we get a null - try { - if (!objectIs(getSnapshot(), renderedValue)) { - // Found an inconsistent store. - return false; - } - } catch (error) { - // If `getSnapshot` throws, return `false`. This will schedule - // a re-render, and the error will be rethrown during render. - return false; - } - } - } - } - } + incompleteWork = returnFiber; // Update the next thing we're working on in case something throws. - var child = node.child; + workInProgress = incompleteWork; + } while (incompleteWork !== null); // We've unwound all the way to the root. - if (node.subtreeFlags & StoreConsistency && child !== null) { - child.return = node; - node = child; - continue; + workInProgressRootExitStatus = RootDidNotComplete; + workInProgress = null; } - if (node === finishedWork) { - return true; - } + function commitRoot(root, recoverableErrors, transitions, spawnedLane) { + // TODO: This no longer makes any sense. We already wrap the mutation and + // layout phases. Should be able to remove. + var previousUpdateLanePriority = getCurrentUpdatePriority(); + var prevTransition = ReactCurrentBatchConfig.transition; - while (node.sibling === null) { - if (node.return === null || node.return === finishedWork) { - return true; + try { + ReactCurrentBatchConfig.transition = null; + setCurrentUpdatePriority(DiscreteEventPriority); + commitRootImpl( + root, + recoverableErrors, + transitions, + previousUpdateLanePriority, + spawnedLane + ); + } finally { + ReactCurrentBatchConfig.transition = prevTransition; + setCurrentUpdatePriority(previousUpdateLanePriority); } - node = node.return; + return null; } - node.sibling.return = node.return; - node = node.sibling; - } // Flow doesn't know this is unreachable, but eslint does - // eslint-disable-next-line no-unreachable - - return true; -} - -function markRootSuspended(root, suspendedLanes, spawnedLane) { - // When suspending, we should always exclude lanes that were pinged or (more - // rarely, since we try to avoid it) updated during the render phase. - // TODO: Lol maybe there's a better way to factor this besides this - // obnoxiously named function :) - suspendedLanes = removeLanes(suspendedLanes, workInProgressRootPingedLanes); - suspendedLanes = removeLanes( - suspendedLanes, - workInProgressRootInterleavedUpdatedLanes - ); - markRootSuspended$1(root, suspendedLanes, spawnedLane); -} // This is the entry point for synchronous tasks that don't go -// through Scheduler - -function performSyncWorkOnRoot(root, lanes) { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - throw new Error("Should not already be working."); - } - - var didFlushPassiveEffects = flushPassiveEffects(); - - if (didFlushPassiveEffects) { - // If passive effects were flushed, exit to the outer work loop in the root - // scheduler, so we can recompute the priority. - // TODO: We don't actually need this `ensureRootIsScheduled` call because - // this path is only reachable if the root is already part of the schedule. - // I'm including it only for consistency with the other exit points from - // this function. Can address in a subsequent refactor. - ensureRootIsScheduled(root); - return null; - } - - { - syncNestedUpdateFlag(); - } - - var exitStatus = renderRootSync(root, lanes); - - if (root.tag !== LegacyRoot && exitStatus === RootErrored) { - // If something threw an error, try rendering one more time. We'll render - // synchronously to block concurrent data mutations, and we'll includes - // all pending updates are included. If it still fails after the second - // attempt, we'll give up and commit the resulting tree. - var originallyAttemptedLanes = lanes; - var errorRetryLanes = getLanesToRetrySynchronouslyOnError( + function commitRootImpl( root, - originallyAttemptedLanes - ); - - if (errorRetryLanes !== NoLanes) { - lanes = errorRetryLanes; - exitStatus = recoverFromConcurrentError( - root, - originallyAttemptedLanes, - errorRetryLanes - ); - } - } - - if (exitStatus === RootFatalErrored) { - var fatalError = workInProgressRootFatalError; - prepareFreshStack(root, NoLanes); - markRootSuspended(root, lanes, NoLane); - ensureRootIsScheduled(root); - throw fatalError; - } - - if (exitStatus === RootDidNotComplete) { - // The render unwound without completing the tree. This happens in special - // cases where need to exit the current render without producing a - // consistent tree or committing. - markRootSuspended(root, lanes, NoLane); - ensureRootIsScheduled(root); - return null; - } // We now have a consistent tree. Because this is a sync render, we - // will commit it even if something suspended. - - var finishedWork = root.current.alternate; - root.finishedWork = finishedWork; - root.finishedLanes = lanes; - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - workInProgressDeferredLane - ); // Before exiting, make sure there's a callback scheduled for the next - // pending level. - - ensureRootIsScheduled(root); - return null; -} -function getExecutionContext() { - return executionContext; -} -// Warning, this opts-out of checking the function body. -// eslint-disable-next-line no-unused-vars -// eslint-disable-next-line no-redeclare -// eslint-disable-next-line no-redeclare - -function flushSync(fn) { - // In legacy mode, we flush pending passive effects at the beginning of the - // next event, not at the end of the previous one. - if ( - rootWithPendingPassiveEffects !== null && - rootWithPendingPassiveEffects.tag === LegacyRoot && - (executionContext & (RenderContext | CommitContext)) === NoContext - ) { - flushPassiveEffects(); - } - - var prevExecutionContext = executionContext; - executionContext |= BatchedContext; - var prevTransition = ReactCurrentBatchConfig.transition; - var previousPriority = getCurrentUpdatePriority(); - - try { - ReactCurrentBatchConfig.transition = null; - setCurrentUpdatePriority(DiscreteEventPriority); - - if (fn) { - return fn(); - } else { - return undefined; - } - } finally { - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; - executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. - // Note that this will happen even if batchedUpdates is higher up - // the stack. - - if ((executionContext & (RenderContext | CommitContext)) === NoContext) { - flushSyncWorkOnAllRoots(); - } - } -} -function isInvalidExecutionContextForEventFunction() { - // Used to throw if certain APIs are called from the wrong context. - return (executionContext & RenderContext) !== NoContext; -} // This is called by the HiddenContext module when we enter or leave a -// hidden subtree. The stack logic is managed there because that's the only -// place that ever modifies it. Which module it lives in doesn't matter for -// performance because this function will get inlined regardless - -function setEntangledRenderLanes(newEntangledRenderLanes) { - entangledRenderLanes = newEntangledRenderLanes; -} -function getEntangledRenderLanes() { - return entangledRenderLanes; -} + recoverableErrors, + transitions, + renderPriorityLevel, + spawnedLane + ) { + do { + // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which + // means `flushPassiveEffects` will sometimes result in additional + // passive effects. So we need to keep flushing in a loop until there are + // no more pending effects. + // TODO: Might be better if `flushPassiveEffects` did not automatically + // flush synchronous work at the end, to avoid factoring hazards like this. + flushPassiveEffects(); + } while (rootWithPendingPassiveEffects !== null); -function resetWorkInProgressStack() { - if (workInProgress === null) return; - var interruptedWork; - - if (workInProgressSuspendedReason === NotSuspended) { - // Normal case. Work-in-progress hasn't started yet. Unwind all - // its parents. - interruptedWork = workInProgress.return; - } else { - // Work-in-progress is in suspended state. Reset the work loop and unwind - // both the suspended fiber and all its parents. - resetSuspendedWorkLoopOnUnwind(workInProgress); - interruptedWork = workInProgress; - } - - while (interruptedWork !== null) { - var current = interruptedWork.alternate; - unwindInterruptedWork(current, interruptedWork); - interruptedWork = interruptedWork.return; - } - - workInProgress = null; -} + flushRenderPhaseStrictModeWarningsInDEV(); -function prepareFreshStack(root, lanes) { - root.finishedWork = null; - root.finishedLanes = NoLanes; - var timeoutHandle = root.timeoutHandle; - - if (timeoutHandle !== noTimeout) { - // The root previous suspended and scheduled a timeout to commit a fallback - // state. Now that we have additional work, cancel the timeout. - root.timeoutHandle = noTimeout; // $FlowFixMe[incompatible-call] Complains noTimeout is not a TimeoutID, despite the check above - - cancelTimeout(timeoutHandle); - } - - var cancelPendingCommit = root.cancelPendingCommit; - - if (cancelPendingCommit !== null) { - root.cancelPendingCommit = null; - cancelPendingCommit(); - } - - resetWorkInProgressStack(); - workInProgressRoot = root; - var rootWorkInProgress = createWorkInProgress(root.current, null); - workInProgress = rootWorkInProgress; - workInProgressRootRenderLanes = lanes; - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - workInProgressRootDidAttachPingListener = false; - workInProgressRootExitStatus = RootInProgress; - workInProgressRootFatalError = null; - workInProgressRootSkippedLanes = NoLanes; - workInProgressRootInterleavedUpdatedLanes = NoLanes; - workInProgressRootPingedLanes = NoLanes; - workInProgressDeferredLane = NoLane; - workInProgressRootConcurrentErrors = null; - workInProgressRootRecoverableErrors = null; // Get the lanes that are entangled with whatever we're about to render. We - // track these separately so we can distinguish the priority of the render - // task from the priority of the lanes it is entangled with. For example, a - // transition may not be allowed to finish unless it includes the Sync lane, - // which is currently suspended. We should be able to render the Transition - // and Sync lane in the same batch, but at Transition priority, because the - // Sync lane already suspended. - - entangledRenderLanes = getEntangledLanes(root, lanes); - finishQueueingConcurrentUpdates(); - - { - ReactStrictModeWarnings.discardPendingWarnings(); - } - - return rootWorkInProgress; -} + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error("Should not already be working."); + } -function resetSuspendedWorkLoopOnUnwind(fiber) { - // Reset module-level state that was set during the render phase. - resetContextDependencies(); - resetHooksOnUnwind(fiber); - resetChildReconcilerOnUnwind(); -} + var finishedWork = root.finishedWork; + var lanes = root.finishedLanes; -function handleThrow(root, thrownValue) { - // A component threw an exception. Usually this is because it suspended, but - // it also includes regular program errors. - // - // We're either going to unwind the stack to show a Suspense or error - // boundary, or we're going to replay the component again. Like after a - // promise resolves. - // - // Until we decide whether we're going to unwind or replay, we should preserve - // the current state of the work loop without resetting anything. - // - // If we do decide to unwind the stack, module-level variables will be reset - // in resetSuspendedWorkLoopOnUnwind. - // These should be reset immediately because they're only supposed to be set - // when React is executing user code. - resetHooksAfterThrow(); - resetCurrentFiber(); - ReactCurrentOwner.current = null; - - if (thrownValue === SuspenseException) { - // This is a special type of exception used for Suspense. For historical - // reasons, the rest of the Suspense implementation expects the thrown value - // to be a thenable, because before `use` existed that was the (unstable) - // API for suspending. This implementation detail can change later, once we - // deprecate the old API in favor of `use`. - thrownValue = getSuspendedThenable(); - workInProgressSuspendedReason = - shouldRemainOnPreviousScreen() && // Check if there are other pending updates that might possibly unblock this - // component from suspending. This mirrors the check in - // renderDidSuspendDelayIfPossible. We should attempt to unify them somehow. - // TODO: Consider unwinding immediately, using the - // SuspendedOnHydration mechanism. - !includesNonIdleWork(workInProgressRootSkippedLanes) && - !includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes) // Suspend work loop until data resolves - ? SuspendedOnData // Don't suspend work loop, except to check if the data has - : // immediately resolved (i.e. in a microtask). Otherwise, trigger the - // nearest Suspense fallback. - SuspendedOnImmediate; - } else if (thrownValue === SuspenseyCommitException) { - thrownValue = getSuspendedThenable(); - workInProgressSuspendedReason = SuspendedOnInstance; - } else if (thrownValue === SelectiveHydrationException) { - // An update flowed into a dehydrated boundary. Before we can apply the - // update, we need to finish hydrating. Interrupt the work-in-progress - // render so we can restart at the hydration lane. - // - // The ideal implementation would be able to switch contexts without - // unwinding the current stack. - // - // We could name this something more general but as of now it's the only - // case where we think this should happen. - workInProgressSuspendedReason = SuspendedOnHydration; - } else { - // This is a regular error. - var isWakeable = - thrownValue !== null && - typeof thrownValue === "object" && - typeof thrownValue.then === "function"; - workInProgressSuspendedReason = isWakeable // A wakeable object was thrown by a legacy Suspense implementation. - ? // This has slightly different behavior than suspending with `use`. - SuspendedOnDeprecatedThrowPromise // This is a regular error. If something earlier in the component already - : // suspended, we must clear the thenable state to unblock the work loop. - SuspendedOnError; - } - - workInProgressThrownValue = thrownValue; - var erroredWork = workInProgress; - - if (erroredWork === null) { - // This is a fatal error - workInProgressRootExitStatus = RootFatalErrored; - workInProgressRootFatalError = thrownValue; - return; - } - - if (erroredWork.mode & ProfileMode) { - // Record the time spent rendering before an error was thrown. This - // avoids inaccurate Profiler durations in the case of a - // suspended render. - stopProfilerTimerIfRunningAndRecordDelta(erroredWork, true); - } - - if (enableSchedulingProfiler) { - markComponentRenderStopped(); - - switch (workInProgressSuspendedReason) { - case SuspendedOnError: { - markComponentErrored( - erroredWork, - thrownValue, - workInProgressRootRenderLanes - ); - break; + { + if (enableDebugTracing) { + logCommitStarted(lanes); + } } - case SuspendedOnData: - case SuspendedOnImmediate: - case SuspendedOnDeprecatedThrowPromise: - case SuspendedAndReadyToContinue: { - var wakeable = thrownValue; - markComponentSuspended( - erroredWork, - wakeable, - workInProgressRootRenderLanes - ); - break; + if (enableSchedulingProfiler) { + markCommitStarted(lanes); } - } - } -} -function shouldRemainOnPreviousScreen() { - // This is asking whether it's better to suspend the transition and remain - // on the previous screen, versus showing a fallback as soon as possible. It - // takes into account both the priority of render and also whether showing a - // fallback would produce a desirable user experience. - var handler = getSuspenseHandler(); - - if (handler === null) { - // There's no Suspense boundary that can provide a fallback. We have no - // choice but to remain on the previous screen. - // NOTE: We do this even for sync updates, for lack of any better option. In - // the future, we may change how we handle this, like by putting the whole - // root into a "detached" mode. - return true; - } // TODO: Once `use` has fully replaced the `throw promise` pattern, we should - // be able to remove the equivalent check in finishConcurrentRender, and rely - // just on this one. - - if (includesOnlyTransitions(workInProgressRootRenderLanes)) { - if (getShellBoundary() === null) { - // We're rendering inside the "shell" of the app. Activating the nearest - // fallback would cause visible content to disappear. It's better to - // suspend the transition and remain on the previous screen. - return true; - } else { - // We're rendering content that wasn't part of the previous screen. - // Rather than block the transition, it's better to show a fallback as - // soon as possible. The appearance of any nested fallbacks will be - // throttled to avoid jank. - return false; - } - } - - if ( - includesOnlyRetries(workInProgressRootRenderLanes) || // In this context, an OffscreenLane counts as a Retry - // TODO: It's become increasingly clear that Retries and Offscreen are - // deeply connected. They probably can be unified further. - includesSomeLane(workInProgressRootRenderLanes, OffscreenLane) - ) { - // During a retry, we can suspend rendering if the nearest Suspense boundary - // is the boundary of the "shell", because we're guaranteed not to block - // any new content from appearing. - // - // The reason we must check if this is a retry is because it guarantees - // that suspending the work loop won't block an actual update, because - // retries don't "update" anything; they fill in fallbacks that were left - // behind by a previous transition. - return handler === getShellBoundary(); - } // For all other Lanes besides Transitions and Retries, we should not wait - // for the data to load. - - return false; -} + if (finishedWork === null) { + { + if (enableDebugTracing) { + logCommitStopped(); + } + } -function pushDispatcher(container) { - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = ContextOnlyDispatcher; - - if (prevDispatcher === null) { - // The React isomorphic package does not include a default dispatcher. - // Instead the first renderer will lazily attach one, in order to give - // nicer error messages. - return ContextOnlyDispatcher; - } else { - return prevDispatcher; - } -} + if (enableSchedulingProfiler) { + markCommitStopped(); + } -function popDispatcher(prevDispatcher) { - ReactCurrentDispatcher.current = prevDispatcher; -} + return null; + } else { + { + if (lanes === NoLanes) { + error( + "root.finishedLanes should not be empty during a commit. This is a " + + "bug in React." + ); + } + } + } -function pushCacheDispatcher() { - { - var prevCacheDispatcher = ReactCurrentCache.current; - ReactCurrentCache.current = DefaultCacheDispatcher; - return prevCacheDispatcher; - } -} + root.finishedWork = null; + root.finishedLanes = NoLanes; -function popCacheDispatcher(prevCacheDispatcher) { - { - ReactCurrentCache.current = prevCacheDispatcher; - } -} + if (finishedWork === root.current) { + throw new Error( + "Cannot commit the same tree as before. This error is likely caused by " + + "a bug in React. Please file an issue." + ); + } // commitRoot never returns a continuation; it always finishes synchronously. + // So we can clear these now to allow a new callback to be scheduled. + + root.callbackNode = null; + root.callbackPriority = NoLane; + root.cancelPendingCommit = null; // Check which lanes no longer have any work scheduled on them, and mark + // those as finished. + + var remainingLanes = mergeLanes( + finishedWork.lanes, + finishedWork.childLanes + ); // Make sure to account for lanes that were updated by a concurrent event + // during the render phase; don't mark them as finished. + + var concurrentlyUpdatedLanes = getConcurrentlyUpdatedLanes(); + remainingLanes = mergeLanes(remainingLanes, concurrentlyUpdatedLanes); + markRootFinished(root, remainingLanes, spawnedLane); + + if (root === workInProgressRoot) { + // We can reset these now that they are finished. + workInProgressRoot = null; + workInProgress = null; + workInProgressRootRenderLanes = NoLanes; + } // If there are pending passive effects, schedule a callback to process them. + // Do this as early as possible, so it is queued before anything else that + // might get scheduled in the commit phase. (See #16714.) + // TODO: Delete all other places that schedule the passive effect callback + // They're redundant. -function markCommitTimeOfFallback() { - globalMostRecentFallbackTime = now$1(); -} -function markSkippedUpdateLanes(lane) { - workInProgressRootSkippedLanes = mergeLanes( - lane, - workInProgressRootSkippedLanes - ); -} -function renderDidSuspend() { - if (workInProgressRootExitStatus === RootInProgress) { - workInProgressRootExitStatus = RootSuspended; - } -} -function renderDidSuspendDelayIfPossible() { - workInProgressRootExitStatus = RootSuspendedWithDelay; // Check if there are updates that we skipped tree that might have unblocked - // this render. - - if ( - (includesNonIdleWork(workInProgressRootSkippedLanes) || - includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes)) && - workInProgressRoot !== null - ) { - // Mark the current render as suspended so that we switch to working on - // the updates that were skipped. Usually we only suspend at the end of - // the render phase. - // TODO: We should probably always mark the root as suspended immediately - // (inside this function), since by suspending at the end of the render - // phase introduces a potential mistake where we suspend lanes that were - // pinged or updated while we were rendering. - // TODO: Consider unwinding immediately, using the - // SuspendedOnHydration mechanism. - markRootSuspended( - workInProgressRoot, - workInProgressRootRenderLanes, - workInProgressDeferredLane - ); - } -} -function renderDidError(error) { - if (workInProgressRootExitStatus !== RootSuspendedWithDelay) { - workInProgressRootExitStatus = RootErrored; - } - - if (workInProgressRootConcurrentErrors === null) { - workInProgressRootConcurrentErrors = [error]; - } else { - workInProgressRootConcurrentErrors.push(error); - } -} // Called during render to determine if anything has suspended. -// Returns false if we're not sure. - -function renderHasNotSuspendedYet() { - // If something errored or completed, we can't really be sure, - // so those are false. - return workInProgressRootExitStatus === RootInProgress; -} // TODO: Over time, this function and renderRootConcurrent have become more -// and more similar. Not sure it makes sense to maintain forked paths. Consider -// unifying them again. - -function renderRootSync(root, lanes) { - var prevExecutionContext = executionContext; - executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(); - var prevCacheDispatcher = pushCacheDispatcher(); // If the root or lanes have changed, throw out the existing stack - // and prepare a fresh one. Otherwise we'll continue where we left off. - - if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { - { - if (isDevToolsPresent) { - var memoizedUpdaters = root.memoizedUpdaters; + if ( + (finishedWork.subtreeFlags & PassiveMask) !== NoFlags$1 || + (finishedWork.flags & PassiveMask) !== NoFlags$1 + ) { + if (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + pendingPassiveEffectsRemainingLanes = remainingLanes; // workInProgressTransitions might be overwritten, so we want + // to store it in pendingPassiveTransitions until they get processed + // We need to pass this through as an argument to commitRoot + // because workInProgressTransitions might have changed between + // the previous render and commit if we throttle the commit + // with setTimeout + + pendingPassiveTransitions = transitions; + scheduleCallback(NormalPriority$1, function () { + flushPassiveEffects(); // This render triggered passive effects: release the root cache pool + // *after* passive effects fire to avoid freeing a cache pool that may + // be referenced by a node in the tree (HostRoot, Cache boundary etc) - if (memoizedUpdaters.size > 0) { - restorePendingUpdaters(root, workInProgressRootRenderLanes); - memoizedUpdaters.clear(); - } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set. - // If we bailout on this work, we'll move them back (like above). - // It's important to move them now in case the work spawns more work at the same priority with different updaters. - // That way we can keep the current update and future updates separate. + return null; + }); + } + } // Check if there are any effects in the whole tree. + // TODO: This is left over from the effect list implementation, where we had + // to check for the existence of `firstEffect` to satisfy Flow. I think the + // only other reason this optimization exists is because it affects profiling. + // Reconsider whether this is necessary. + + var subtreeHasEffects = + (finishedWork.subtreeFlags & + (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== + NoFlags$1; + var rootHasEffect = + (finishedWork.flags & + (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== + NoFlags$1; + + if (subtreeHasEffects || rootHasEffect) { + var prevTransition = ReactCurrentBatchConfig.transition; + ReactCurrentBatchConfig.transition = null; + var previousPriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority(DiscreteEventPriority); + var prevExecutionContext = executionContext; + executionContext |= CommitContext; // Reset this to null before calling lifecycles + + ReactCurrentOwner.current = null; // The commit phase is broken into several sub-phases. We do a separate pass + // of the effect list for each phase: all mutation effects come before all + // layout effects, and so on. + // The first phase a "before mutation" phase. We use this phase to read the + // state of the host tree right before we mutate it. This is where + // getSnapshotBeforeUpdate is called. + + commitBeforeMutationEffects(root, finishedWork); - movePendingFibersToMemoized(root, lanes); - } - } + { + // Mark the current commit time to be shared by all Profilers in this + // batch. This enables them to be grouped later. + recordCommitTime(); + } - workInProgressTransitions = getTransitionsForLanes(root, lanes); - prepareFreshStack(root, lanes); - } + if (enableProfilerNestedUpdateScheduledHook) { + // Track the root here, rather than in commitLayoutEffects(), because of ref setters. + // Updates scheduled during ref detachment should also be flagged. + rootCommittingMutationOrLayoutEffects = root; + } // The next phase is the mutation phase, where we mutate the host tree. - { - if (enableDebugTracing) { - logRenderStarted(lanes); - } - } + commitMutationEffects(root, finishedWork, lanes); + // the mutation phase, so that the previous tree is still current during + // componentWillUnmount, but before the layout phase, so that the finished + // work is current during componentDidMount/Update. - if (enableSchedulingProfiler) { - markRenderStarted(lanes); - } + root.current = finishedWork; // The next phase is the layout phase, where we call effects that read + // the host tree after it's been mutated. The idiomatic use case for this is + // layout, but class component lifecycles also fire here for legacy reasons. - var didSuspendInShell = false; + { + if (enableDebugTracing) { + logLayoutEffectsStarted(lanes); + } + } - outer: do { - try { - if ( - workInProgressSuspendedReason !== NotSuspended && - workInProgress !== null - ) { - // The work loop is suspended. During a synchronous render, we don't - // yield to the main thread. Immediately unwind the stack. This will - // trigger either a fallback or an error boundary. - // TODO: For discrete and "default" updates (anything that's not - // flushSync), we want to wait for the microtasks the flush before - // unwinding. Will probably implement this using renderRootConcurrent, - // or merge renderRootSync and renderRootConcurrent into the same - // function and fork the behavior some other way. - var unitOfWork = workInProgress; - var thrownValue = workInProgressThrownValue; + if (enableSchedulingProfiler) { + markLayoutEffectsStarted(lanes); + } - switch (workInProgressSuspendedReason) { - case SuspendedOnHydration: { - // Selective hydration. An update flowed into a dehydrated tree. - // Interrupt the current render so the work loop can switch to the - // hydration lane. - resetWorkInProgressStack(); - workInProgressRootExitStatus = RootDidNotComplete; - break outer; - } + commitLayoutEffects(finishedWork, root, lanes); - case SuspendedOnImmediate: - case SuspendedOnData: { - if (!didSuspendInShell && getSuspenseHandler() === null) { - didSuspendInShell = true; - } // Intentional fallthrough + { + if (enableDebugTracing) { + logLayoutEffectsStopped(); } + } - default: { - // Unwind then continue with the normal work loop. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); - break; - } + if (enableSchedulingProfiler) { + markLayoutEffectsStopped(); } - } - workLoopSync(); - break; - } catch (thrownValue) { - handleThrow(root, thrownValue); - } - } while (true); // Check if something suspended in the shell. We use this to detect an - // infinite ping loop caused by an uncached promise. - // - // Only increment this counter once per synchronous render attempt across the - // whole tree. Even if there are many sibling components that suspend, this - // counter only gets incremented once. + if (enableProfilerNestedUpdateScheduledHook) { + rootCommittingMutationOrLayoutEffects = null; + } // Tell Scheduler to yield at the end of the frame, so the browser has an + // opportunity to paint. - if (didSuspendInShell) { - root.shellSuspendCounter++; - } + requestPaint(); + executionContext = prevExecutionContext; // Reset the priority to the previous non-sync value. - resetContextDependencies(); - executionContext = prevExecutionContext; - popDispatcher(prevDispatcher); - popCacheDispatcher(prevCacheDispatcher); + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig.transition = prevTransition; + } else { + // No effects. + root.current = finishedWork; // Measure these anyway so the flamegraph explicitly shows that there were + // no effects. + // TODO: Maybe there's a better way to report this. - if (workInProgress !== null) { - // This is a sync render, so we should have finished the whole tree. - throw new Error( - "Cannot commit an incomplete root. This error is likely caused by a " + - "bug in React. Please file an issue." - ); - } + { + recordCommitTime(); + } + } - { - if (enableDebugTracing) { - logRenderStopped(); - } - } + var rootDidHavePassiveEffects = rootDoesHavePassiveEffects; + + if (rootDoesHavePassiveEffects) { + // This commit has passive effects. Stash a reference to them. But don't + // schedule a callback until after flushing layout work. + rootDoesHavePassiveEffects = false; + rootWithPendingPassiveEffects = root; + pendingPassiveEffectsLanes = lanes; + } else { + // There were no passive effects, so we can immediately release the cache + // pool for this render. + releaseRootPooledCache(root, remainingLanes); - if (enableSchedulingProfiler) { - markRenderStopped(); - } // Set this to null to indicate there's no in-progress render. + { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = null; + } + } // Read this again, since an effect might have updated it - workInProgressRoot = null; - workInProgressRootRenderLanes = NoLanes; // It's safe to process the queue now that the render phase is complete. + remainingLanes = root.pendingLanes; // Check if there's remaining work on this root + // TODO: This is part of the `componentDidCatch` implementation. Its purpose + // is to detect whether something might have called setState inside + // `componentDidCatch`. The mechanism is known to be flawed because `setState` + // inside `componentDidCatch` is itself flawed — that's why we recommend + // `getDerivedStateFromError` instead. However, it could be improved by + // checking if remainingLanes includes Sync work, instead of whether there's + // any work remaining at all (which would also include stuff like Suspense + // retries or transitions). It's been like this for a while, though, so fixing + // it probably isn't that urgent. - finishQueueingConcurrentUpdates(); - return workInProgressRootExitStatus; -} // The work loop is an extremely hot path. Tell Closure not to inline it. + if (remainingLanes === NoLanes) { + // If there's no remaining work, we can clear the set of already failed + // error boundaries. + legacyErrorBoundariesThatAlreadyFailed = null; + } -/** @noinline */ + { + if (!rootDidHavePassiveEffects) { + commitDoubleInvokeEffectsInDEV(root, false); + } + } -function workLoopSync() { - // Perform work without checking if we need to yield between fiber. - while (workInProgress !== null) { - performUnitOfWork(workInProgress); - } -} + onCommitRoot(finishedWork.stateNode, renderPriorityLevel); -function renderRootConcurrent(root, lanes) { - var prevExecutionContext = executionContext; - executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(); - var prevCacheDispatcher = pushCacheDispatcher(); // If the root or lanes have changed, throw out the existing stack - // and prepare a fresh one. Otherwise we'll continue where we left off. + { + if (isDevToolsPresent) { + root.memoizedUpdaters.clear(); + } + } + // additional work on this root is scheduled. - if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { - { - if (isDevToolsPresent) { - var memoizedUpdaters = root.memoizedUpdaters; + ensureRootIsScheduled(root); - if (memoizedUpdaters.size > 0) { - restorePendingUpdaters(root, workInProgressRootRenderLanes); - memoizedUpdaters.clear(); - } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set. - // If we bailout on this work, we'll move them back (like above). - // It's important to move them now in case the work spawns more work at the same priority with different updaters. - // That way we can keep the current update and future updates separate. + if (recoverableErrors !== null) { + // There were errors during this render, but recovered from them without + // needing to surface it to the UI. We log them here. + var onRecoverableError = root.onRecoverableError; - movePendingFibersToMemoized(root, lanes); + for (var i = 0; i < recoverableErrors.length; i++) { + var recoverableError = recoverableErrors[i]; + var errorInfo = makeErrorInfo( + recoverableError.digest, + recoverableError.stack + ); + onRecoverableError(recoverableError.value, errorInfo); + } } - } - workInProgressTransitions = getTransitionsForLanes(root, lanes); - resetRenderTimer(); - prepareFreshStack(root, lanes); - } + if (hasUncaughtError) { + hasUncaughtError = false; + var error$1 = firstUncaughtError; + firstUncaughtError = null; + throw error$1; + } // If the passive effects are the result of a discrete render, flush them + // synchronously at the end of the current task so that the result is + // immediately observable. Otherwise, we assume that they are not + // order-dependent and do not need to be observed by external systems, so we + // can wait until after paint. + // TODO: We can optimize this by not scheduling the callback earlier. Since we + // currently schedule the callback in multiple places, will wait until those + // are consolidated. - { - if (enableDebugTracing) { - logRenderStarted(lanes); - } - } + if ( + includesSyncLane(pendingPassiveEffectsLanes) && + root.tag !== LegacyRoot + ) { + flushPassiveEffects(); + } // Read this again, since a passive effect might have updated it - if (enableSchedulingProfiler) { - markRenderStarted(lanes); - } + remainingLanes = root.pendingLanes; // Check if this render scheduled a cascading synchronous update. This is a + // heurstic to detect infinite update loops. We are intentionally excluding + // hydration lanes in this check, because render triggered by selective + // hydration is conceptually not an update. - outer: do { - try { if ( - workInProgressSuspendedReason !== NotSuspended && - workInProgress !== null + // Was the finished render the result of an update (not hydration)? + includesSomeLane(lanes, UpdateLanes) && // Did it schedule a sync update? + includesSomeLane(remainingLanes, SyncUpdateLanes) ) { - // The work loop is suspended. We need to either unwind the stack or - // replay the suspended component. - var unitOfWork = workInProgress; - var thrownValue = workInProgressThrownValue; + { + markNestedUpdateScheduled(); + } // Count the number of times the root synchronously re-renders without + // finishing. If there are too many, it indicates an infinite update loop. - resumeOrUnwind: switch (workInProgressSuspendedReason) { - case SuspendedOnError: { - // Unwind then continue with the normal work loop. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); - break; - } + if (root === rootWithNestedUpdates) { + nestedUpdateCount++; + } else { + nestedUpdateCount = 0; + rootWithNestedUpdates = root; + } + } else { + nestedUpdateCount = 0; + } // If layout work was scheduled, flush it now. - case SuspendedOnData: { - var thenable = thrownValue; + flushSyncWorkOnAllRoots(); - if (isThenableResolved(thenable)) { - // The data resolved. Try rendering the component again. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - replaySuspendedUnitOfWork(unitOfWork); - break; - } // The work loop is suspended on data. We should wait for it to - // resolve before continuing to render. - // TODO: Handle the case where the promise resolves synchronously. - // Usually this is handled when we instrument the promise to add a - // `status` field, but if the promise already has a status, we won't - // have added a listener until right here. - - var onResolution = function () { - // Check if the root is still suspended on this promise. - if ( - workInProgressSuspendedReason === SuspendedOnData && - workInProgressRoot === root - ) { - // Mark the root as ready to continue rendering. - workInProgressSuspendedReason = SuspendedAndReadyToContinue; - } // Ensure the root is scheduled. We should do this even if we're - // currently working on a different root, so that we resume - // rendering later. + { + if (enableDebugTracing) { + logCommitStopped(); + } + } - ensureRootIsScheduled(root); - }; + if (enableSchedulingProfiler) { + markCommitStopped(); + } - thenable.then(onResolution, onResolution); - break outer; - } + return null; + } - case SuspendedOnImmediate: { - // If this fiber just suspended, it's possible the data is already - // cached. Yield to the main thread to give it a chance to ping. If - // it does, we can retry immediately without unwinding the stack. - workInProgressSuspendedReason = SuspendedAndReadyToContinue; - break outer; - } + function makeErrorInfo(digest, componentStack) { + { + var errorInfo = { + componentStack: componentStack, + digest: digest + }; + Object.defineProperty(errorInfo, "digest", { + configurable: false, + enumerable: true, + get: function () { + error( + 'You are accessing "digest" from the errorInfo object passed to onRecoverableError.' + + " This property is deprecated and will be removed in a future version of React." + + " To access the digest of an Error look for this property on the Error instance itself." + ); - case SuspendedOnInstance: { - workInProgressSuspendedReason = - SuspendedOnInstanceAndReadyToContinue; - break outer; + return digest; } + }); + return errorInfo; + } + } - case SuspendedAndReadyToContinue: { - var _thenable = thrownValue; + function releaseRootPooledCache(root, remainingLanes) { + { + var pooledCacheLanes = (root.pooledCacheLanes &= remainingLanes); - if (isThenableResolved(_thenable)) { - // The data resolved. Try rendering the component again. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - replaySuspendedUnitOfWork(unitOfWork); - } else { - // Otherwise, unwind then continue with the normal work loop. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); - } + if (pooledCacheLanes === NoLanes) { + // None of the remaining work relies on the cache pool. Clear it so + // subsequent requests get a new cache + var pooledCache = root.pooledCache; - break; + if (pooledCache != null) { + root.pooledCache = null; + releaseCache(pooledCache); } + } + } + } - case SuspendedOnInstanceAndReadyToContinue: { - switch (workInProgress.tag) { - case HostComponent: - case HostHoistable: - case HostSingleton: { - // Before unwinding the stack, check one more time if the - // instance is ready. It may have loaded when React yielded to - // the main thread. - // Assigning this to a constant so Flow knows the binding won't - // be mutated by `preloadInstance`. - var hostFiber = workInProgress; - var type = hostFiber.type; - var props = hostFiber.pendingProps; - var isReady = preloadInstance(type, props); - - if (isReady) { - // The data resolved. Resume the work loop as if nothing - // suspended. Unlike when a user component suspends, we don't - // have to replay anything because the host fiber - // already completed. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - var sibling = hostFiber.sibling; + function flushPassiveEffects() { + // Returns whether passive effects were flushed. + // TODO: Combine this check with the one in flushPassiveEFfectsImpl. We should + // probably just combine the two functions. I believe they were only separate + // in the first place because we used to wrap it with + // `Scheduler.runWithPriority`, which accepts a function. But now we track the + // priority within React itself, so we can mutate the variable directly. + if (rootWithPendingPassiveEffects !== null) { + // Cache the root since rootWithPendingPassiveEffects is cleared in + // flushPassiveEffectsImpl + var root = rootWithPendingPassiveEffects; // Cache and clear the remaining lanes flag; it must be reset since this + // method can be called from various places, not always from commitRoot + // where the remaining lanes are known - if (sibling !== null) { - workInProgress = sibling; - } else { - var returnFiber = hostFiber.return; + var remainingLanes = pendingPassiveEffectsRemainingLanes; + pendingPassiveEffectsRemainingLanes = NoLanes; + var renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes); + var priority = lowerEventPriority(DefaultEventPriority, renderPriority); + var prevTransition = ReactCurrentBatchConfig.transition; + var previousPriority = getCurrentUpdatePriority(); - if (returnFiber !== null) { - workInProgress = returnFiber; - completeUnitOfWork(returnFiber); - } else { - workInProgress = null; - } - } + try { + ReactCurrentBatchConfig.transition = null; + setCurrentUpdatePriority(priority); + return flushPassiveEffectsImpl(); + } finally { + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig.transition = prevTransition; // Once passive effects have run for the tree - giving components a + // chance to retain cache instances they use - release the pooled + // cache at the root (if there is one) - break resumeOrUnwind; - } + releaseRootPooledCache(root, remainingLanes); + } + } - break; - } + return false; + } + function enqueuePendingPassiveProfilerEffect(fiber) { + { + pendingPassiveProfilerEffects.push(fiber); - default: { - // This will fail gracefully but it's not correct, so log a - // warning in dev. - if (true) { - error( - "Unexpected type of fiber triggered a suspensey commit. " + - "This is a bug in React." - ); - } + if (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + scheduleCallback(NormalPriority$1, function () { + flushPassiveEffects(); + return null; + }); + } + } + } - break; - } - } // Otherwise, unwind then continue with the normal work loop. + function flushPassiveEffectsImpl() { + if (rootWithPendingPassiveEffects === null) { + return false; + } // Cache and clear the transitions flag - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); - break; - } + var transitions = pendingPassiveTransitions; + pendingPassiveTransitions = null; + var root = rootWithPendingPassiveEffects; + var lanes = pendingPassiveEffectsLanes; + rootWithPendingPassiveEffects = null; // TODO: This is sometimes out of sync with rootWithPendingPassiveEffects. + // Figure out why and fix it. It's not causing any known issues (probably + // because it's only used for profiling), but it's a refactor hazard. - case SuspendedOnDeprecatedThrowPromise: { - // Suspended by an old implementation that uses the `throw promise` - // pattern. The newer replaying behavior can cause subtle issues - // like infinite ping loops. So we maintain the old behavior and - // always unwind. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); - break; - } + pendingPassiveEffectsLanes = NoLanes; - case SuspendedOnHydration: { - // Selective hydration. An update flowed into a dehydrated tree. - // Interrupt the current render so the work loop can switch to the - // hydration lane. - resetWorkInProgressStack(); - workInProgressRootExitStatus = RootDidNotComplete; - break outer; - } + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error( + "Cannot flush passive effects while already rendering." + ); + } - default: { - throw new Error( - "Unexpected SuspendedReason. This is a bug in React." - ); - } + { + isFlushingPassiveEffects = true; + didScheduleUpdateDuringPassiveEffects = false; + + if (enableDebugTracing) { + logPassiveEffectsStarted(lanes); } } - if (true && ReactCurrentActQueue.current !== null) { - // `act` special case: If we're inside an `act` scope, don't consult - // `shouldYield`. Always keep working until the render is complete. - // This is not just an optimization: in a unit test environment, we - // can't trust the result of `shouldYield`, because the host I/O is - // likely mocked. - workLoopSync(); - } else { - workLoopConcurrent(); + if (enableSchedulingProfiler) { + markPassiveEffectsStarted(lanes); } - break; - } catch (thrownValue) { - handleThrow(root, thrownValue); - } - } while (true); + var prevExecutionContext = executionContext; + executionContext |= CommitContext; + commitPassiveUnmountEffects(root.current); + commitPassiveMountEffects(root, root.current, lanes, transitions); // TODO: Move to commitPassiveMountEffects - resetContextDependencies(); - popDispatcher(prevDispatcher); - popCacheDispatcher(prevCacheDispatcher); - executionContext = prevExecutionContext; + { + var profilerEffects = pendingPassiveProfilerEffects; + pendingPassiveProfilerEffects = []; - { - if (enableDebugTracing) { - logRenderStopped(); - } - } // Check if the tree has completed. + for (var i = 0; i < profilerEffects.length; i++) { + var fiber = profilerEffects[i]; + commitPassiveEffectDurations(root, fiber); + } + } - if (workInProgress !== null) { - // Still work remaining. - if (enableSchedulingProfiler) { - markRenderYielded(); - } + { + if (enableDebugTracing) { + logPassiveEffectsStopped(); + } + } - return RootInProgress; - } else { - // Completed the tree. - if (enableSchedulingProfiler) { - markRenderStopped(); - } // Set this to null to indicate there's no in-progress render. + if (enableSchedulingProfiler) { + markPassiveEffectsStopped(); + } + + { + commitDoubleInvokeEffectsInDEV(root, true); + } - workInProgressRoot = null; - workInProgressRootRenderLanes = NoLanes; // It's safe to process the queue now that the render phase is complete. + executionContext = prevExecutionContext; + flushSyncWorkOnAllRoots(); - finishQueueingConcurrentUpdates(); // Return the final exit status. + if (enableTransitionTracing) { + var prevPendingTransitionCallbacks = currentPendingTransitionCallbacks; + var prevRootTransitionCallbacks = root.transitionCallbacks; + var prevEndTime = currentEndTime; - return workInProgressRootExitStatus; - } -} -/** @noinline */ - -function workLoopConcurrent() { - // Perform work until Scheduler asks us to yield - while (workInProgress !== null && !shouldYield()) { - // $FlowFixMe[incompatible-call] found when upgrading Flow - performUnitOfWork(workInProgress); - } -} + if ( + prevPendingTransitionCallbacks !== null && + prevRootTransitionCallbacks !== null && + prevEndTime !== null + ) { + currentPendingTransitionCallbacks = null; + currentEndTime = null; + scheduleCallback(IdlePriority, function () { + processTransitionCallbacks( + prevPendingTransitionCallbacks, + prevEndTime, + prevRootTransitionCallbacks + ); + }); + } + } + + { + // If additional passive effects were scheduled, increment a counter. If this + // exceeds the limit, we'll fire a warning. + if (didScheduleUpdateDuringPassiveEffects) { + if (root === rootWithPassiveNestedUpdates) { + nestedPassiveUpdateCount++; + } else { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = root; + } + } else { + nestedPassiveUpdateCount = 0; + } -function performUnitOfWork(unitOfWork) { - // The current, flushed, state of this fiber is the alternate. Ideally - // nothing should rely on this, but relying on it here means that we don't - // need an additional field on the work in progress. - var current = unitOfWork.alternate; - setCurrentFiber(unitOfWork); - var next; - - if ((unitOfWork.mode & ProfileMode) !== NoMode) { - startProfilerTimer(unitOfWork); - next = beginWork(current, unitOfWork, entangledRenderLanes); - stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); - } else { - next = beginWork(current, unitOfWork, entangledRenderLanes); - } - - resetCurrentFiber(); - unitOfWork.memoizedProps = unitOfWork.pendingProps; - - if (next === null) { - // If this doesn't spawn new work, complete the current work. - completeUnitOfWork(unitOfWork); - } else { - workInProgress = next; - } - - ReactCurrentOwner.current = null; -} + isFlushingPassiveEffects = false; + didScheduleUpdateDuringPassiveEffects = false; + } // TODO: Move to commitPassiveMountEffects -function replaySuspendedUnitOfWork(unitOfWork) { - // This is a fork of performUnitOfWork specifcally for replaying a fiber that - // just suspended. - // - var current = unitOfWork.alternate; - setCurrentFiber(unitOfWork); - var next; - setCurrentFiber(unitOfWork); - var isProfilingMode = (unitOfWork.mode & ProfileMode) !== NoMode; - - if (isProfilingMode) { - startProfilerTimer(unitOfWork); - } - - switch (unitOfWork.tag) { - case IndeterminateComponent: { - // Because it suspended with `use`, we can assume it's a - // function component. - unitOfWork.tag = FunctionComponent; // Fallthrough to the next branch. - } - - case SimpleMemoComponent: - case FunctionComponent: { - // Resolve `defaultProps`. This logic is copied from `beginWork`. - // TODO: Consider moving this switch statement into that module. Also, - // could maybe use this as an opportunity to say `use` doesn't work with - // `defaultProps` :) - var Component = unitOfWork.type; - var unresolvedProps = unitOfWork.pendingProps; - var resolvedProps = - unitOfWork.elementType === Component - ? unresolvedProps - : resolveDefaultProps(Component, unresolvedProps); - var context; + onPostCommitRoot(root); { - var unmaskedContext = getUnmaskedContext(unitOfWork, Component, true); - context = getMaskedContext(unitOfWork, unmaskedContext); + var stateNode = root.current.stateNode; + stateNode.effectDuration = 0; + stateNode.passiveEffectDuration = 0; } - next = replayFunctionComponent( - current, - unitOfWork, - resolvedProps, - Component, - context, - workInProgressRootRenderLanes - ); - break; + return true; } - case ForwardRef: { - // Resolve `defaultProps`. This logic is copied from `beginWork`. - // TODO: Consider moving this switch statement into that module. Also, - // could maybe use this as an opportunity to say `use` doesn't work with - // `defaultProps` :) - var _Component = unitOfWork.type.render; - var _unresolvedProps = unitOfWork.pendingProps; - - var _resolvedProps = - unitOfWork.elementType === _Component - ? _unresolvedProps - : resolveDefaultProps(_Component, _unresolvedProps); - - next = replayFunctionComponent( - current, - unitOfWork, - _resolvedProps, - _Component, - unitOfWork.ref, - workInProgressRootRenderLanes + function isAlreadyFailedLegacyErrorBoundary(instance) { + return ( + legacyErrorBoundariesThatAlreadyFailed !== null && + legacyErrorBoundariesThatAlreadyFailed.has(instance) ); - break; } - - case HostComponent: { - // Some host components are stateful (that's how we implement form - // actions) but we don't bother to reuse the memoized state because it's - // not worth the extra code. The main reason to reuse the previous hooks - // is to reuse uncached promises, but we happen to know that the only - // promises that a host component might suspend on are definitely cached - // because they are controlled by us. So don't bother. - resetHooksOnUnwind(unitOfWork); // Fallthrough to the next branch. + function markLegacyErrorBoundaryAsFailed(instance) { + if (legacyErrorBoundariesThatAlreadyFailed === null) { + legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); + } else { + legacyErrorBoundariesThatAlreadyFailed.add(instance); + } } - default: { - // Other types besides function components are reset completely before - // being replayed. Currently this only happens when a Usable type is - // reconciled — the reconciler will suspend. - // - // We reset the fiber back to its original state; however, this isn't - // a full "unwind" because we're going to reuse the promises that were - // reconciled previously. So it's intentional that we don't call - // resetSuspendedWorkLoopOnUnwind here. - unwindInterruptedWork(current, unitOfWork); - unitOfWork = workInProgress = resetWorkInProgress( - unitOfWork, - entangledRenderLanes - ); - next = beginWork(current, unitOfWork, entangledRenderLanes); - break; + function prepareToThrowUncaughtError(error) { + if (!hasUncaughtError) { + hasUncaughtError = true; + firstUncaughtError = error; + } } - } - - if (isProfilingMode) { - stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); - } // The begin phase finished successfully without suspending. Return to the - // normal work loop. - - resetCurrentFiber(); - unitOfWork.memoizedProps = unitOfWork.pendingProps; - - if (next === null) { - // If this doesn't spawn new work, complete the current work. - completeUnitOfWork(unitOfWork); - } else { - workInProgress = next; - } - - ReactCurrentOwner.current = null; -} -function throwAndUnwindWorkLoop(unitOfWork, thrownValue) { - // This is a fork of performUnitOfWork specifcally for unwinding a fiber - // that threw an exception. - // - // Return to the normal work loop. This will unwind the stack, and potentially - // result in showing a fallback. - resetSuspendedWorkLoopOnUnwind(unitOfWork); - var returnFiber = unitOfWork.return; - - if (returnFiber === null || workInProgressRoot === null) { - // Expected to be working on a non-root fiber. This is a fatal error - // because there's no ancestor that can handle it; the root is - // supposed to capture all errors that weren't caught by an error - // boundary. - workInProgressRootExitStatus = RootFatalErrored; - workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next - // sibling, or the parent if there are no siblings. But since the root - // has no siblings nor a parent, we set it to null. Usually this is - // handled by `completeUnitOfWork` or `unwindWork`, but since we're - // intentionally not calling those, we need set it here. - // TODO: Consider calling `unwindWork` to pop the contexts. - - workInProgress = null; - return; - } - - try { - // Find and mark the nearest Suspense or error boundary that can handle - // this "exception". - throwException( - workInProgressRoot, - returnFiber, - unitOfWork, - thrownValue, - workInProgressRootRenderLanes - ); - } catch (error) { - // We had trouble processing the error. An example of this happening is - // when accessing the `componentDidCatch` property of an error boundary - // throws an error. A weird edge case. There's a regression test for this. - // To prevent an infinite loop, bubble the error up to the next parent. - workInProgress = returnFiber; - throw error; - } - - if (unitOfWork.flags & Incomplete) { - // Unwind the stack until we reach the nearest boundary. - unwindUnitOfWork(unitOfWork); - } else { - // Although the fiber suspended, we're intentionally going to commit it in - // an inconsistent state. We can do this safely in cases where we know the - // inconsistent tree will be hidden. - // - // This currently only applies to Legacy Suspense implementation, but we may - // port a version of this to concurrent roots, too, when performing a - // synchronous render. Because that will allow us to mutate the tree as we - // go instead of buffering mutations until the end. Though it's unclear if - // this particular path is how that would be implemented. - completeUnitOfWork(unitOfWork); - } -} + var onUncaughtError = prepareToThrowUncaughtError; -function completeUnitOfWork(unitOfWork) { - // Attempt to complete the current unit of work, then move to the next - // sibling. If there are no more siblings, return to the parent fiber. - var completedWork = unitOfWork; + function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { + var errorInfo = createCapturedValueAtFiber(error, sourceFiber); + var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane); + var root = enqueueUpdate(rootFiber, update, SyncLane); - do { - { - if ((completedWork.flags & Incomplete) !== NoFlags$1) { - // NOTE: If we re-enable sibling prerendering in some cases, this branch - // is where we would switch to the unwinding path. - error( - "Internal React error: Expected this fiber to be complete, but " + - "it isn't. It should have been unwound. This is a bug in React." - ); + if (root !== null) { + markRootUpdated(root, SyncLane); + ensureRootIsScheduled(root); } - } // The current, flushed, state of this fiber is the alternate. Ideally - // nothing should rely on this, but relying on it here means that we don't - // need an additional field on the work in progress. - - var current = completedWork.alternate; - var returnFiber = completedWork.return; - setCurrentFiber(completedWork); - var next = void 0; - - if ((completedWork.mode & ProfileMode) === NoMode) { - next = completeWork(current, completedWork, entangledRenderLanes); - } else { - startProfilerTimer(completedWork); - next = completeWork(current, completedWork, entangledRenderLanes); // Update render duration assuming we didn't error. - - stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); } - resetCurrentFiber(); - - if (next !== null) { - // Completing this fiber spawned new work. Work on that next. - workInProgress = next; - return; - } - - var siblingFiber = completedWork.sibling; + function captureCommitPhaseError( + sourceFiber, + nearestMountedAncestor, + error$1 + ) { + { + reportUncaughtErrorInDEV(error$1); + setIsRunningInsertionEffect(false); + } - if (siblingFiber !== null) { - // If there is more work to do in this returnFiber, do that next. - workInProgress = siblingFiber; - return; - } // Otherwise, return to the parent - // $FlowFixMe[incompatible-type] we bail out when we get a null + if (sourceFiber.tag === HostRoot) { + // Error was thrown at the root. There is no parent, so the root + // itself should capture it. + captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error$1); + return; + } - completedWork = returnFiber; // Update the next thing we're working on in case something throws. + var fiber = nearestMountedAncestor; - workInProgress = completedWork; - } while (completedWork !== null); // We've reached the root. + while (fiber !== null) { + if (fiber.tag === HostRoot) { + captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error$1); + return; + } else if (fiber.tag === ClassComponent) { + var ctor = fiber.type; + var instance = fiber.stateNode; - if (workInProgressRootExitStatus === RootInProgress) { - workInProgressRootExitStatus = RootCompleted; - } -} + if ( + typeof ctor.getDerivedStateFromError === "function" || + (typeof instance.componentDidCatch === "function" && + !isAlreadyFailedLegacyErrorBoundary(instance)) + ) { + var errorInfo = createCapturedValueAtFiber(error$1, sourceFiber); + var update = createClassErrorUpdate(fiber, errorInfo, SyncLane); + var root = enqueueUpdate(fiber, update, SyncLane); -function unwindUnitOfWork(unitOfWork) { - var incompleteWork = unitOfWork; + if (root !== null) { + markRootUpdated(root, SyncLane); + ensureRootIsScheduled(root); + } - do { - // The current, flushed, state of this fiber is the alternate. Ideally - // nothing should rely on this, but relying on it here means that we don't - // need an additional field on the work in progress. - var current = incompleteWork.alternate; // This fiber did not complete because something threw. Pop values off - // the stack without entering the complete phase. If this is a boundary, - // capture values if possible. + return; + } + } - var next = unwindWork(current, incompleteWork); // Because this fiber did not complete, don't reset its lanes. + fiber = fiber.return; + } - if (next !== null) { - // Found a boundary that can handle this exception. Re-renter the - // begin phase. This branch will return us to the normal work loop. + { + error( + "Internal React error: Attempted to capture a commit phase error " + + "inside a detached tree. This indicates a bug in React. Potential " + + "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 + ); + } + } + function attachPingListener(root, wakeable, lanes) { + // Attach a ping listener // - // Since we're restarting, remove anything that is not a host effect - // from the effect tag. - next.flags &= HostEffectMask; - workInProgress = next; - return; - } // Keep unwinding until we reach either a boundary or the root. + // The data might resolve before we have a chance to commit the fallback. Or, + // in the case of a refresh, we'll never commit a fallback. So we need to + // attach a listener now. When it resolves ("pings"), we can decide whether to + // try rendering the tree again. + // + // Only attach a listener if one does not already exist for the lanes + // we're currently rendering (which acts like a "thread ID" here). + // + // We only need to do this in concurrent mode. Legacy Suspense always + // commits fallbacks synchronously, so there are no pings. + var pingCache = root.pingCache; + var threadIDs; + + if (pingCache === null) { + pingCache = root.pingCache = new PossiblyWeakMap(); + threadIDs = new Set(); + pingCache.set(wakeable, threadIDs); + } else { + threadIDs = pingCache.get(wakeable); - if ((incompleteWork.mode & ProfileMode) !== NoMode) { - // Record the render duration for the fiber that errored. - stopProfilerTimerIfRunningAndRecordDelta(incompleteWork, false); // Include the time spent working on failed children before continuing. + if (threadIDs === undefined) { + threadIDs = new Set(); + pingCache.set(wakeable, threadIDs); + } + } - var actualDuration = incompleteWork.actualDuration; - var child = incompleteWork.child; + if (!threadIDs.has(lanes)) { + workInProgressRootDidAttachPingListener = true; // Memoize using the thread ID to prevent redundant listeners. - while (child !== null) { - // $FlowFixMe[unsafe-addition] addition with possible null/undefined value - actualDuration += child.actualDuration; - child = child.sibling; - } + threadIDs.add(lanes); + var ping = pingSuspendedRoot.bind(null, root, wakeable, lanes); - incompleteWork.actualDuration = actualDuration; - } // TODO: Once we stop prerendering siblings, instead of resetting the parent - // of the node being unwound, we should be able to reset node itself as we - // unwind the stack. Saves an additional null check. + { + if (isDevToolsPresent) { + // If we have pending work still, restore the original updaters + restorePendingUpdaters(root, lanes); + } + } - var returnFiber = incompleteWork.return; + wakeable.then(ping, ping); + } + } - if (returnFiber !== null) { - // Mark the parent fiber as incomplete and clear its subtree flags. - // TODO: Once we stop prerendering siblings, we may be able to get rid of - // the Incomplete flag because unwinding to the nearest boundary will - // happen synchronously. - returnFiber.flags |= Incomplete; - returnFiber.subtreeFlags = NoFlags$1; - returnFiber.deletions = null; - } // NOTE: If we re-enable sibling prerendering in some cases, here we - // would switch to the normal completion path: check if a sibling - // exists, and if so, begin work on it. - // Otherwise, return to the parent - // $FlowFixMe[incompatible-type] we bail out when we get a null + function pingSuspendedRoot(root, wakeable, pingedLanes) { + var pingCache = root.pingCache; - incompleteWork = returnFiber; // Update the next thing we're working on in case something throws. + if (pingCache !== null) { + // The wakeable resolved, so we no longer need to memoize, because it will + // never be thrown again. + pingCache.delete(wakeable); + } - workInProgress = incompleteWork; - } while (incompleteWork !== null); // We've unwound all the way to the root. + markRootPinged(root, pingedLanes); + warnIfSuspenseResolutionNotWrappedWithActDEV(root); - workInProgressRootExitStatus = RootDidNotComplete; - workInProgress = null; -} + if ( + workInProgressRoot === root && + isSubsetOfLanes(workInProgressRootRenderLanes, pingedLanes) + ) { + // Received a ping at the same priority level at which we're currently + // rendering. We might want to restart this render. This should mirror + // the logic of whether or not a root suspends once it completes. + // TODO: If we're rendering sync either due to Sync, Batched or expired, + // we should probably never restart. + // If we're suspended with delay, or if it's a retry, we'll always suspend + // so we can always restart. + if ( + workInProgressRootExitStatus === RootSuspendedWithDelay || + (workInProgressRootExitStatus === RootSuspended && + includesOnlyRetries(workInProgressRootRenderLanes) && + now$1() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) + ) { + // Force a restart from the root by unwinding the stack. Unless this is + // being called from the render phase, because that would cause a crash. + if ((executionContext & RenderContext) === NoContext) { + prepareFreshStack(root, NoLanes); + } + } else { + // Even though we can't restart right now, we might get an + // opportunity later. So we mark this render as having a ping. + workInProgressRootPingedLanes = mergeLanes( + workInProgressRootPingedLanes, + pingedLanes + ); + } + } -function commitRoot(root, recoverableErrors, transitions, spawnedLane) { - // TODO: This no longer makes any sense. We already wrap the mutation and - // layout phases. Should be able to remove. - var previousUpdateLanePriority = getCurrentUpdatePriority(); - var prevTransition = ReactCurrentBatchConfig.transition; + ensureRootIsScheduled(root); + } - try { - ReactCurrentBatchConfig.transition = null; - setCurrentUpdatePriority(DiscreteEventPriority); - commitRootImpl( - root, - recoverableErrors, - transitions, - previousUpdateLanePriority, - spawnedLane - ); - } finally { - ReactCurrentBatchConfig.transition = prevTransition; - setCurrentUpdatePriority(previousUpdateLanePriority); - } + function retryTimedOutBoundary(boundaryFiber, retryLane) { + // The boundary fiber (a Suspense component or SuspenseList component) + // previously was rendered in its fallback state. One of the promises that + // suspended it has resolved, which means at least part of the tree was + // likely unblocked. Try rendering again, at a new lanes. + if (retryLane === NoLane) { + // TODO: Assign this to `suspenseState.retryLane`? to avoid + // unnecessary entanglement? + retryLane = requestRetryLane(boundaryFiber); + } // TODO: Special case idle priority? - return null; -} + var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); -function commitRootImpl( - root, - recoverableErrors, - transitions, - renderPriorityLevel, - spawnedLane -) { - do { - // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which - // means `flushPassiveEffects` will sometimes result in additional - // passive effects. So we need to keep flushing in a loop until there are - // no more pending effects. - // TODO: Might be better if `flushPassiveEffects` did not automatically - // flush synchronous work at the end, to avoid factoring hazards like this. - flushPassiveEffects(); - } while (rootWithPendingPassiveEffects !== null); - - flushRenderPhaseStrictModeWarningsInDEV(); - - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - throw new Error("Should not already be working."); - } - - var finishedWork = root.finishedWork; - var lanes = root.finishedLanes; - - { - if (enableDebugTracing) { - logCommitStarted(lanes); - } - } - - if (enableSchedulingProfiler) { - markCommitStarted(lanes); - } - - if (finishedWork === null) { - { - if (enableDebugTracing) { - logCommitStopped(); + if (root !== null) { + markRootUpdated(root, retryLane); + ensureRootIsScheduled(root); } } - if (enableSchedulingProfiler) { - markCommitStopped(); - } + function retryDehydratedSuspenseBoundary(boundaryFiber) { + var suspenseState = boundaryFiber.memoizedState; + var retryLane = NoLane; - return null; - } else { - { - if (lanes === NoLanes) { - error( - "root.finishedLanes should not be empty during a commit. This is a " + - "bug in React." - ); + if (suspenseState !== null) { + retryLane = suspenseState.retryLane; } + + retryTimedOutBoundary(boundaryFiber, retryLane); } - } + function resolveRetryWakeable(boundaryFiber, wakeable) { + var retryLane = NoLane; // Default - root.finishedWork = null; - root.finishedLanes = NoLanes; + var retryCache; - if (finishedWork === root.current) { - throw new Error( - "Cannot commit the same tree as before. This error is likely caused by " + - "a bug in React. Please file an issue." - ); - } // commitRoot never returns a continuation; it always finishes synchronously. - // So we can clear these now to allow a new callback to be scheduled. - - root.callbackNode = null; - root.callbackPriority = NoLane; - root.cancelPendingCommit = null; // Check which lanes no longer have any work scheduled on them, and mark - // those as finished. - - var remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes); // Make sure to account for lanes that were updated by a concurrent event - // during the render phase; don't mark them as finished. - - var concurrentlyUpdatedLanes = getConcurrentlyUpdatedLanes(); - remainingLanes = mergeLanes(remainingLanes, concurrentlyUpdatedLanes); - markRootFinished(root, remainingLanes, spawnedLane); - - if (root === workInProgressRoot) { - // We can reset these now that they are finished. - workInProgressRoot = null; - workInProgress = null; - workInProgressRootRenderLanes = NoLanes; - } // If there are pending passive effects, schedule a callback to process them. - // Do this as early as possible, so it is queued before anything else that - // might get scheduled in the commit phase. (See #16714.) - // TODO: Delete all other places that schedule the passive effect callback - // They're redundant. - - if ( - (finishedWork.subtreeFlags & PassiveMask) !== NoFlags$1 || - (finishedWork.flags & PassiveMask) !== NoFlags$1 - ) { - if (!rootDoesHavePassiveEffects) { - rootDoesHavePassiveEffects = true; - pendingPassiveEffectsRemainingLanes = remainingLanes; // workInProgressTransitions might be overwritten, so we want - // to store it in pendingPassiveTransitions until they get processed - // We need to pass this through as an argument to commitRoot - // because workInProgressTransitions might have changed between - // the previous render and commit if we throttle the commit - // with setTimeout - - pendingPassiveTransitions = transitions; - scheduleCallback(NormalPriority$1, function () { - flushPassiveEffects(); // This render triggered passive effects: release the root cache pool - // *after* passive effects fire to avoid freeing a cache pool that may - // be referenced by a node in the tree (HostRoot, Cache boundary etc) + switch (boundaryFiber.tag) { + case SuspenseComponent: + retryCache = boundaryFiber.stateNode; + var suspenseState = boundaryFiber.memoizedState; - return null; - }); - } - } // Check if there are any effects in the whole tree. - // TODO: This is left over from the effect list implementation, where we had - // to check for the existence of `firstEffect` to satisfy Flow. I think the - // only other reason this optimization exists is because it affects profiling. - // Reconsider whether this is necessary. - - var subtreeHasEffects = - (finishedWork.subtreeFlags & - (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== - NoFlags$1; - var rootHasEffect = - (finishedWork.flags & - (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== - NoFlags$1; - - if (subtreeHasEffects || rootHasEffect) { - var prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = null; - var previousPriority = getCurrentUpdatePriority(); - setCurrentUpdatePriority(DiscreteEventPriority); - var prevExecutionContext = executionContext; - executionContext |= CommitContext; // Reset this to null before calling lifecycles - - ReactCurrentOwner.current = null; // The commit phase is broken into several sub-phases. We do a separate pass - // of the effect list for each phase: all mutation effects come before all - // layout effects, and so on. - // The first phase a "before mutation" phase. We use this phase to read the - // state of the host tree right before we mutate it. This is where - // getSnapshotBeforeUpdate is called. - - commitBeforeMutationEffects(root, finishedWork); + if (suspenseState !== null) { + retryLane = suspenseState.retryLane; + } - { - // Mark the current commit time to be shared by all Profilers in this - // batch. This enables them to be grouped later. - recordCommitTime(); - } + break; - if (enableProfilerNestedUpdateScheduledHook) { - // Track the root here, rather than in commitLayoutEffects(), because of ref setters. - // Updates scheduled during ref detachment should also be flagged. - rootCommittingMutationOrLayoutEffects = root; - } // The next phase is the mutation phase, where we mutate the host tree. + case SuspenseListComponent: + retryCache = boundaryFiber.stateNode; + break; - commitMutationEffects(root, finishedWork, lanes); - // the mutation phase, so that the previous tree is still current during - // componentWillUnmount, but before the layout phase, so that the finished - // work is current during componentDidMount/Update. + case OffscreenComponent: { + var instance = boundaryFiber.stateNode; + retryCache = instance._retryCache; + break; + } - root.current = finishedWork; // The next phase is the layout phase, where we call effects that read - // the host tree after it's been mutated. The idiomatic use case for this is - // layout, but class component lifecycles also fire here for legacy reasons. + default: + throw new Error( + "Pinged unknown suspense boundary type. " + + "This is probably a bug in React." + ); + } - { - if (enableDebugTracing) { - logLayoutEffectsStarted(lanes); + if (retryCache !== null) { + // The wakeable resolved, so we no longer need to memoize, because it will + // never be thrown again. + retryCache.delete(wakeable); } - } - if (enableSchedulingProfiler) { - markLayoutEffectsStarted(lanes); + retryTimedOutBoundary(boundaryFiber, retryLane); } + function throwIfInfiniteUpdateLoopDetected() { + if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { + nestedUpdateCount = 0; + nestedPassiveUpdateCount = 0; + rootWithNestedUpdates = null; + rootWithPassiveNestedUpdates = null; + 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." + ); + } - commitLayoutEffects(finishedWork, root, lanes); + { + if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = null; - { - if (enableDebugTracing) { - logLayoutEffectsStopped(); + 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." + ); + } } } - if (enableSchedulingProfiler) { - markLayoutEffectsStopped(); + function flushRenderPhaseStrictModeWarningsInDEV() { + { + ReactStrictModeWarnings.flushLegacyContextWarning(); + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); + } } - if (enableProfilerNestedUpdateScheduledHook) { - rootCommittingMutationOrLayoutEffects = null; - } // Tell Scheduler to yield at the end of the frame, so the browser has an - // opportunity to paint. - - requestPaint(); - executionContext = prevExecutionContext; // Reset the priority to the previous non-sync value. - - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; - } else { - // No effects. - root.current = finishedWork; // Measure these anyway so the flamegraph explicitly shows that there were - // no effects. - // TODO: Maybe there's a better way to report this. - - { - recordCommitTime(); + function commitDoubleInvokeEffectsInDEV(root, hasPassiveEffects) { + { + { + legacyCommitDoubleInvokeEffectsInDEV(root.current, hasPassiveEffects); + } + } } - } - var rootDidHavePassiveEffects = rootDoesHavePassiveEffects; - - if (rootDoesHavePassiveEffects) { - // This commit has passive effects. Stash a reference to them. But don't - // schedule a callback until after flushing layout work. - rootDoesHavePassiveEffects = false; - rootWithPendingPassiveEffects = root; - pendingPassiveEffectsLanes = lanes; - } else { - // There were no passive effects, so we can immediately release the cache - // pool for this render. - releaseRootPooledCache(root, remainingLanes); + function legacyCommitDoubleInvokeEffectsInDEV(fiber, hasPassiveEffects) { + // TODO (StrictEffects) Should we set a marker on the root if it contains strict effects + // so we don't traverse unnecessarily? similar to subtreeFlags but just at the root level. + // Maybe not a big deal since this is DEV only behavior. + setCurrentFiber(fiber); + invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectUnmountInDEV); - { - nestedPassiveUpdateCount = 0; - rootWithPassiveNestedUpdates = null; - } - } // Read this again, since an effect might have updated it - - remainingLanes = root.pendingLanes; // Check if there's remaining work on this root - // TODO: This is part of the `componentDidCatch` implementation. Its purpose - // is to detect whether something might have called setState inside - // `componentDidCatch`. The mechanism is known to be flawed because `setState` - // inside `componentDidCatch` is itself flawed — that's why we recommend - // `getDerivedStateFromError` instead. However, it could be improved by - // checking if remainingLanes includes Sync work, instead of whether there's - // any work remaining at all (which would also include stuff like Suspense - // retries or transitions). It's been like this for a while, though, so fixing - // it probably isn't that urgent. - - if (remainingLanes === NoLanes) { - // If there's no remaining work, we can clear the set of already failed - // error boundaries. - legacyErrorBoundariesThatAlreadyFailed = null; - } - - { - if (!rootDidHavePassiveEffects) { - commitDoubleInvokeEffectsInDEV(root, false); - } - } - - onCommitRoot(finishedWork.stateNode, renderPriorityLevel); - - { - if (isDevToolsPresent) { - root.memoizedUpdaters.clear(); - } - } - // additional work on this root is scheduled. - - ensureRootIsScheduled(root); - - if (recoverableErrors !== null) { - // There were errors during this render, but recovered from them without - // needing to surface it to the UI. We log them here. - var onRecoverableError = root.onRecoverableError; - - for (var i = 0; i < recoverableErrors.length; i++) { - var recoverableError = recoverableErrors[i]; - var errorInfo = makeErrorInfo( - recoverableError.digest, - recoverableError.stack - ); - onRecoverableError(recoverableError.value, errorInfo); - } - } - - if (hasUncaughtError) { - hasUncaughtError = false; - var error$1 = firstUncaughtError; - firstUncaughtError = null; - throw error$1; - } // If the passive effects are the result of a discrete render, flush them - // synchronously at the end of the current task so that the result is - // immediately observable. Otherwise, we assume that they are not - // order-dependent and do not need to be observed by external systems, so we - // can wait until after paint. - // TODO: We can optimize this by not scheduling the callback earlier. Since we - // currently schedule the callback in multiple places, will wait until those - // are consolidated. - - if (includesSyncLane(pendingPassiveEffectsLanes) && root.tag !== LegacyRoot) { - flushPassiveEffects(); - } // Read this again, since a passive effect might have updated it - - remainingLanes = root.pendingLanes; // Check if this render scheduled a cascading synchronous update. This is a - // heurstic to detect infinite update loops. We are intentionally excluding - // hydration lanes in this check, because render triggered by selective - // hydration is conceptually not an update. - - if ( - // Was the finished render the result of an update (not hydration)? - includesSomeLane(lanes, UpdateLanes) && // Did it schedule a sync update? - includesSomeLane(remainingLanes, SyncUpdateLanes) - ) { - { - markNestedUpdateScheduled(); - } // Count the number of times the root synchronously re-renders without - // finishing. If there are too many, it indicates an infinite update loop. + if (hasPassiveEffects) { + invokeEffectsInDev( + fiber, + MountPassiveDev, + invokePassiveEffectUnmountInDEV + ); + } - if (root === rootWithNestedUpdates) { - nestedUpdateCount++; - } else { - nestedUpdateCount = 0; - rootWithNestedUpdates = root; - } - } else { - nestedUpdateCount = 0; - } // If layout work was scheduled, flush it now. + invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectMountInDEV); - flushSyncWorkOnAllRoots(); + if (hasPassiveEffects) { + invokeEffectsInDev( + fiber, + MountPassiveDev, + invokePassiveEffectMountInDEV + ); + } - { - if (enableDebugTracing) { - logCommitStopped(); + resetCurrentFiber(); } - } - if (enableSchedulingProfiler) { - markCommitStopped(); - } + function invokeEffectsInDev(firstChild, fiberFlags, invokeEffectFn) { + var current = firstChild; + var subtreeRoot = null; - return null; -} + while (current != null) { + var primarySubtreeFlag = current.subtreeFlags & fiberFlags; -function makeErrorInfo(digest, componentStack) { - { - var errorInfo = { - componentStack: componentStack, - digest: digest - }; - Object.defineProperty(errorInfo, "digest", { - configurable: false, - enumerable: true, - get: function () { - error( - 'You are accessing "digest" from the errorInfo object passed to onRecoverableError.' + - " This property is deprecated and will be removed in a future version of React." + - " To access the digest of an Error look for this property on the Error instance itself." - ); + if ( + current !== subtreeRoot && + current.child != null && + primarySubtreeFlag !== NoFlags$1 + ) { + current = current.child; + } else { + if ((current.flags & fiberFlags) !== NoFlags$1) { + invokeEffectFn(current); + } - return digest; + if (current.sibling !== null) { + current = current.sibling; + } else { + current = subtreeRoot = current.return; + } + } } - }); - return errorInfo; - } -} - -function releaseRootPooledCache(root, remainingLanes) { - { - var pooledCacheLanes = (root.pooledCacheLanes &= remainingLanes); + } - if (pooledCacheLanes === NoLanes) { - // None of the remaining work relies on the cache pool. Clear it so - // subsequent requests get a new cache - var pooledCache = root.pooledCache; + var didWarnStateUpdateForNotYetMountedComponent = null; + function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { + { + if ((executionContext & RenderContext) !== NoContext) { + // We let the other warning about render phase updates deal with this one. + return; + } - if (pooledCache != null) { - root.pooledCache = null; - releaseCache(pooledCache); - } - } - } -} + if (!(fiber.mode & ConcurrentMode)) { + return; + } -function flushPassiveEffects() { - // Returns whether passive effects were flushed. - // TODO: Combine this check with the one in flushPassiveEFfectsImpl. We should - // probably just combine the two functions. I believe they were only separate - // in the first place because we used to wrap it with - // `Scheduler.runWithPriority`, which accepts a function. But now we track the - // priority within React itself, so we can mutate the variable directly. - if (rootWithPendingPassiveEffects !== null) { - // Cache the root since rootWithPendingPassiveEffects is cleared in - // flushPassiveEffectsImpl - var root = rootWithPendingPassiveEffects; // Cache and clear the remaining lanes flag; it must be reset since this - // method can be called from various places, not always from commitRoot - // where the remaining lanes are known - - var remainingLanes = pendingPassiveEffectsRemainingLanes; - pendingPassiveEffectsRemainingLanes = NoLanes; - var renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes); - var priority = lowerEventPriority(DefaultEventPriority, renderPriority); - var prevTransition = ReactCurrentBatchConfig.transition; - var previousPriority = getCurrentUpdatePriority(); - - try { - ReactCurrentBatchConfig.transition = null; - setCurrentUpdatePriority(priority); - return flushPassiveEffectsImpl(); - } finally { - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; // Once passive effects have run for the tree - giving components a - // chance to retain cache instances they use - release the pooled - // cache at the root (if there is one) - - releaseRootPooledCache(root, remainingLanes); - } - } - - return false; -} -function enqueuePendingPassiveProfilerEffect(fiber) { - { - pendingPassiveProfilerEffects.push(fiber); + var tag = fiber.tag; - if (!rootDoesHavePassiveEffects) { - rootDoesHavePassiveEffects = true; - scheduleCallback(NormalPriority$1, function () { - flushPassiveEffects(); - return null; - }); - } - } -} + if ( + tag !== IndeterminateComponent && + tag !== HostRoot && + tag !== ClassComponent && + tag !== FunctionComponent && + tag !== ForwardRef && + tag !== MemoComponent && + tag !== SimpleMemoComponent + ) { + // Only warn for user-defined components, not internal ones like Suspense. + return; + } // We show the whole stack but dedupe on the top component's name because + // the problematic code almost always lies inside that component. -function flushPassiveEffectsImpl() { - if (rootWithPendingPassiveEffects === null) { - return false; - } // Cache and clear the transitions flag + var componentName = + getComponentNameFromFiber(fiber) || "ReactComponent"; - var transitions = pendingPassiveTransitions; - pendingPassiveTransitions = null; - var root = rootWithPendingPassiveEffects; - var lanes = pendingPassiveEffectsLanes; - rootWithPendingPassiveEffects = null; // TODO: This is sometimes out of sync with rootWithPendingPassiveEffects. - // Figure out why and fix it. It's not causing any known issues (probably - // because it's only used for profiling), but it's a refactor hazard. + if (didWarnStateUpdateForNotYetMountedComponent !== null) { + if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) { + return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow - pendingPassiveEffectsLanes = NoLanes; + didWarnStateUpdateForNotYetMountedComponent.add(componentName); + } else { + didWarnStateUpdateForNotYetMountedComponent = new Set([ + componentName + ]); + } - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - throw new Error("Cannot flush passive effects while already rendering."); - } + var previousFiber = current; - { - isFlushingPassiveEffects = true; - didScheduleUpdateDuringPassiveEffects = false; + try { + setCurrentFiber(fiber); - if (enableDebugTracing) { - logPassiveEffectsStarted(lanes); + 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." + ); + } finally { + if (previousFiber) { + setCurrentFiber(fiber); + } else { + resetCurrentFiber(); + } + } + } } - } - - if (enableSchedulingProfiler) { - markPassiveEffectsStarted(lanes); - } + var beginWork; - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - commitPassiveUnmountEffects(root.current); - commitPassiveMountEffects(root, root.current, lanes, transitions); // TODO: Move to commitPassiveMountEffects + if (replayFailedUnitOfWorkWithInvokeGuardedCallback) { + var dummyFiber = null; - { - var profilerEffects = pendingPassiveProfilerEffects; - pendingPassiveProfilerEffects = []; + beginWork = function (current, unitOfWork, lanes) { + // If a component throws an error, we replay it again in a synchronously + // dispatched event, so that the debugger will treat it as an uncaught + // error See ReactErrorUtils for more information. + // Before entering the begin phase, copy the work-in-progress onto a dummy + // fiber. If beginWork throws, we'll use this to reset the state. + var originalWorkInProgressCopy = assignFiberPropertiesInDEV( + dummyFiber, + unitOfWork + ); - for (var i = 0; i < profilerEffects.length; i++) { - var fiber = profilerEffects[i]; - commitPassiveEffectDurations(root, fiber); - } - } + try { + return beginWork$1(current, unitOfWork, lanes); + } catch (originalError) { + if ( + didSuspendOrErrorWhileHydratingDEV() || + originalError === SuspenseException || + originalError === SelectiveHydrationException || + (originalError !== null && + typeof originalError === "object" && + typeof originalError.then === "function") + ) { + // Don't replay promises. + // Don't replay errors if we are hydrating and have already suspended or handled an error + throw originalError; + } // Don't reset current debug fiber, since we're about to work on the + // same fiber again. + // Unwind the failed stack frame - { - if (enableDebugTracing) { - logPassiveEffectsStopped(); - } - } + resetSuspendedWorkLoopOnUnwind(unitOfWork); + unwindInterruptedWork(current, unitOfWork); // Restore the original properties of the fiber. - if (enableSchedulingProfiler) { - markPassiveEffectsStopped(); - } + assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); - { - commitDoubleInvokeEffectsInDEV(root, true); - } + if (unitOfWork.mode & ProfileMode) { + // Reset the profiler timer. + startProfilerTimer(unitOfWork); + } // Run beginWork again. - executionContext = prevExecutionContext; - flushSyncWorkOnAllRoots(); + invokeGuardedCallback( + null, + beginWork$1, + null, + current, + unitOfWork, + lanes + ); - if (enableTransitionTracing) { - var prevPendingTransitionCallbacks = currentPendingTransitionCallbacks; - var prevRootTransitionCallbacks = root.transitionCallbacks; - var prevEndTime = currentEndTime; + if (hasCaughtError()) { + var replayError = clearCaughtError(); - if ( - prevPendingTransitionCallbacks !== null && - prevRootTransitionCallbacks !== null && - prevEndTime !== null - ) { - currentPendingTransitionCallbacks = null; - currentEndTime = null; - scheduleCallback(IdlePriority, function () { - processTransitionCallbacks( - prevPendingTransitionCallbacks, - prevEndTime, - prevRootTransitionCallbacks - ); - }); - } - } + if ( + typeof replayError === "object" && + replayError !== null && + replayError._suppressLogging && + typeof originalError === "object" && + originalError !== null && + !originalError._suppressLogging + ) { + // If suppressed, let the flag carry over to the original error which is the one we'll rethrow. + originalError._suppressLogging = true; + } + } // We always throw the original error in case the second render pass is not idempotent. + // This can happen if a memoized function or CommonJS module doesn't throw after first invocation. - { - // If additional passive effects were scheduled, increment a counter. If this - // exceeds the limit, we'll fire a warning. - if (didScheduleUpdateDuringPassiveEffects) { - if (root === rootWithPassiveNestedUpdates) { - nestedPassiveUpdateCount++; - } else { - nestedPassiveUpdateCount = 0; - rootWithPassiveNestedUpdates = root; - } + throw originalError; + } + }; } else { - nestedPassiveUpdateCount = 0; + beginWork = beginWork$1; } - isFlushingPassiveEffects = false; - didScheduleUpdateDuringPassiveEffects = false; - } // TODO: Move to commitPassiveMountEffects + var didWarnAboutUpdateInRender = false; + var didWarnAboutUpdateInRenderForAnotherComponent; - onPostCommitRoot(root); - - { - var stateNode = root.current.stateNode; - stateNode.effectDuration = 0; - stateNode.passiveEffectDuration = 0; - } - - return true; -} + { + didWarnAboutUpdateInRenderForAnotherComponent = new Set(); + } -function isAlreadyFailedLegacyErrorBoundary(instance) { - return ( - legacyErrorBoundariesThatAlreadyFailed !== null && - legacyErrorBoundariesThatAlreadyFailed.has(instance) - ); -} -function markLegacyErrorBoundaryAsFailed(instance) { - if (legacyErrorBoundariesThatAlreadyFailed === null) { - legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); - } else { - legacyErrorBoundariesThatAlreadyFailed.add(instance); - } -} + function warnAboutRenderPhaseUpdatesInDEV(fiber) { + { + if (isRendering) { + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + var renderingComponentName = + (workInProgress && getComponentNameFromFiber(workInProgress)) || + "Unknown"; // Dedupe by the rendering component because it's the one that needs to be fixed. -function prepareToThrowUncaughtError(error) { - if (!hasUncaughtError) { - hasUncaughtError = true; - firstUncaughtError = error; - } -} + var dedupeKey = renderingComponentName; -var onUncaughtError = prepareToThrowUncaughtError; + if ( + !didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey) + ) { + didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey); + var setStateComponentName = + getComponentNameFromFiber(fiber) || "Unknown"; -function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { - var errorInfo = createCapturedValueAtFiber(error, sourceFiber); - var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane); - var root = enqueueUpdate(rootFiber, update, SyncLane); + 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 + ); + } - if (root !== null) { - markRootUpdated(root, SyncLane); - ensureRootIsScheduled(root); - } -} + break; + } -function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error$1) { - { - reportUncaughtErrorInDEV(error$1); - setIsRunningInsertionEffect(false); - } - - if (sourceFiber.tag === HostRoot) { - // Error was thrown at the root. There is no parent, so the root - // itself should capture it. - captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error$1); - return; - } - - var fiber = nearestMountedAncestor; - - while (fiber !== null) { - if (fiber.tag === HostRoot) { - captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error$1); - return; - } else if (fiber.tag === ClassComponent) { - var ctor = fiber.type; - var instance = fiber.stateNode; + case ClassComponent: { + if (!didWarnAboutUpdateInRender) { + error( + "Cannot update during an existing state transition (such as " + + "within `render`). Render methods should be a pure " + + "function of props and state." + ); - if ( - typeof ctor.getDerivedStateFromError === "function" || - (typeof instance.componentDidCatch === "function" && - !isAlreadyFailedLegacyErrorBoundary(instance)) - ) { - var errorInfo = createCapturedValueAtFiber(error$1, sourceFiber); - var update = createClassErrorUpdate(fiber, errorInfo, SyncLane); - var root = enqueueUpdate(fiber, update, SyncLane); + didWarnAboutUpdateInRender = true; + } - if (root !== null) { - markRootUpdated(root, SyncLane); - ensureRootIsScheduled(root); + break; + } + } } - - return; } } - fiber = fiber.return; - } - - { - error( - "Internal React error: Attempted to capture a commit phase error " + - "inside a detached tree. This indicates a bug in React. Potential " + - "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 - ); - } -} -function attachPingListener(root, wakeable, lanes) { - // Attach a ping listener - // - // The data might resolve before we have a chance to commit the fallback. Or, - // in the case of a refresh, we'll never commit a fallback. So we need to - // attach a listener now. When it resolves ("pings"), we can decide whether to - // try rendering the tree again. - // - // Only attach a listener if one does not already exist for the lanes - // we're currently rendering (which acts like a "thread ID" here). - // - // We only need to do this in concurrent mode. Legacy Suspense always - // commits fallbacks synchronously, so there are no pings. - var pingCache = root.pingCache; - var threadIDs; - - if (pingCache === null) { - pingCache = root.pingCache = new PossiblyWeakMap(); - threadIDs = new Set(); - pingCache.set(wakeable, threadIDs); - } else { - threadIDs = pingCache.get(wakeable); - - if (threadIDs === undefined) { - threadIDs = new Set(); - pingCache.set(wakeable, threadIDs); - } - } - - if (!threadIDs.has(lanes)) { - workInProgressRootDidAttachPingListener = true; // Memoize using the thread ID to prevent redundant listeners. - - threadIDs.add(lanes); - var ping = pingSuspendedRoot.bind(null, root, wakeable, lanes); - - { - if (isDevToolsPresent) { - // If we have pending work still, restore the original updaters - restorePendingUpdaters(root, lanes); + function restorePendingUpdaters(root, lanes) { + { + if (isDevToolsPresent) { + var memoizedUpdaters = root.memoizedUpdaters; + memoizedUpdaters.forEach(function (schedulingFiber) { + addFiberToLanesMap(root, schedulingFiber, lanes); + }); // This function intentionally does not clear memoized updaters. + // Those may still be relevant to the current commit + // and a future one (e.g. Suspense). + } } } + var fakeActCallbackNode = {}; // $FlowFixMe[missing-local-annot] - wakeable.then(ping, ping); - } -} + function scheduleCallback(priorityLevel, callback) { + { + // If we're currently inside an `act` scope, bypass Scheduler and push to + // the `act` queue instead. + var actQueue = ReactCurrentActQueue.current; -function pingSuspendedRoot(root, wakeable, pingedLanes) { - var pingCache = root.pingCache; - - if (pingCache !== null) { - // The wakeable resolved, so we no longer need to memoize, because it will - // never be thrown again. - pingCache.delete(wakeable); - } - - markRootPinged(root, pingedLanes); - warnIfSuspenseResolutionNotWrappedWithActDEV(root); - - if ( - workInProgressRoot === root && - isSubsetOfLanes(workInProgressRootRenderLanes, pingedLanes) - ) { - // Received a ping at the same priority level at which we're currently - // rendering. We might want to restart this render. This should mirror - // the logic of whether or not a root suspends once it completes. - // TODO: If we're rendering sync either due to Sync, Batched or expired, - // we should probably never restart. - // If we're suspended with delay, or if it's a retry, we'll always suspend - // so we can always restart. - if ( - workInProgressRootExitStatus === RootSuspendedWithDelay || - (workInProgressRootExitStatus === RootSuspended && - includesOnlyRetries(workInProgressRootRenderLanes) && - now$1() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) - ) { - // Force a restart from the root by unwinding the stack. Unless this is - // being called from the render phase, because that would cause a crash. - if ((executionContext & RenderContext) === NoContext) { - prepareFreshStack(root, NoLanes); + if (actQueue !== null) { + actQueue.push(callback); + return fakeActCallbackNode; + } else { + return scheduleCallback$3(priorityLevel, callback); + } } - } else { - // Even though we can't restart right now, we might get an - // opportunity later. So we mark this render as having a ping. - workInProgressRootPingedLanes = mergeLanes( - workInProgressRootPingedLanes, - pingedLanes - ); } - } - - ensureRootIsScheduled(root); -} -function retryTimedOutBoundary(boundaryFiber, retryLane) { - // The boundary fiber (a Suspense component or SuspenseList component) - // previously was rendered in its fallback state. One of the promises that - // suspended it has resolved, which means at least part of the tree was - // likely unblocked. Try rendering again, at a new lanes. - if (retryLane === NoLane) { - // TODO: Assign this to `suspenseState.retryLane`? to avoid - // unnecessary entanglement? - retryLane = requestRetryLane(boundaryFiber); - } // TODO: Special case idle priority? - - var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); - - if (root !== null) { - markRootUpdated(root, retryLane); - ensureRootIsScheduled(root); - } -} + function shouldForceFlushFallbacksInDEV() { + // Never force flush in production. This function should get stripped out. + return ReactCurrentActQueue.current !== null; + } -function retryDehydratedSuspenseBoundary(boundaryFiber) { - var suspenseState = boundaryFiber.memoizedState; - var retryLane = NoLane; + function warnIfUpdatesNotWrappedWithActDEV(fiber) { + { + if (fiber.mode & ConcurrentMode) { + if (!isConcurrentActEnvironment()) { + // Not in an act environment. No need to warn. + return; + } + } else { + // Legacy mode has additional cases where we suppress a warning. + if (!isLegacyActEnvironment()) { + // Not in an act environment. No need to warn. + return; + } - if (suspenseState !== null) { - retryLane = suspenseState.retryLane; - } + if (executionContext !== NoContext) { + // Legacy mode doesn't warn if the update is batched, i.e. + // batchedUpdates or flushSync. + return; + } - retryTimedOutBoundary(boundaryFiber, retryLane); -} -function resolveRetryWakeable(boundaryFiber, wakeable) { - var retryLane = NoLane; // Default + if ( + fiber.tag !== FunctionComponent && + fiber.tag !== ForwardRef && + fiber.tag !== SimpleMemoComponent + ) { + // For backwards compatibility with pre-hooks code, legacy mode only + // warns for updates that originate from a hook. + return; + } + } - var retryCache; + if (ReactCurrentActQueue.current === null) { + var previousFiber = current; - switch (boundaryFiber.tag) { - case SuspenseComponent: - retryCache = boundaryFiber.stateNode; - var suspenseState = boundaryFiber.memoizedState; + try { + setCurrentFiber(fiber); - if (suspenseState !== null) { - retryLane = suspenseState.retryLane; + 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) + ); + } finally { + if (previousFiber) { + setCurrentFiber(fiber); + } else { + resetCurrentFiber(); + } + } + } } + } - break; - - case SuspenseListComponent: - retryCache = boundaryFiber.stateNode; - break; + function warnIfSuspenseResolutionNotWrappedWithActDEV(root) { + { + if ( + root.tag !== LegacyRoot && + isConcurrentActEnvironment() && + ReactCurrentActQueue.current === null + ) { + 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" + ); + } + } + } - case OffscreenComponent: { - var instance = boundaryFiber.stateNode; - retryCache = instance._retryCache; - break; + function setIsRunningInsertionEffect(isRunning) { + { + isRunningInsertionEffect = isRunning; + } } - default: - throw new Error( - "Pinged unknown suspense boundary type. " + - "This is probably a bug in React." - ); - } + /* eslint-disable react-internal/prod-error-codes */ + // Used by React Refresh runtime through DevTools Global Hook. - if (retryCache !== null) { - // The wakeable resolved, so we no longer need to memoize, because it will - // never be thrown again. - retryCache.delete(wakeable); - } + var resolveFamily = null; + var failedBoundaries = null; + var setRefreshHandler = function (handler) { + { + resolveFamily = handler; + } + }; + function resolveFunctionForHotReloading(type) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return type; + } - retryTimedOutBoundary(boundaryFiber, retryLane); -} -function throwIfInfiniteUpdateLoopDetected() { - if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { - nestedUpdateCount = 0; - nestedPassiveUpdateCount = 0; - rootWithNestedUpdates = null; - rootWithPassiveNestedUpdates = null; - 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." - ); - } - - { - if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { - nestedPassiveUpdateCount = 0; - rootWithPassiveNestedUpdates = null; - - 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." - ); - } - } -} + var family = resolveFamily(type); -function flushRenderPhaseStrictModeWarningsInDEV() { - { - ReactStrictModeWarnings.flushLegacyContextWarning(); - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); - } -} + if (family === undefined) { + return type; + } // Use the latest known implementation. -function commitDoubleInvokeEffectsInDEV(root, hasPassiveEffects) { - { - { - legacyCommitDoubleInvokeEffectsInDEV(root.current, hasPassiveEffects); + return family.current; + } } - } -} + function resolveClassForHotReloading(type) { + // No implementation differences. + return resolveFunctionForHotReloading(type); + } + function resolveForwardRefForHotReloading(type) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return type; + } -function legacyCommitDoubleInvokeEffectsInDEV(fiber, hasPassiveEffects) { - // TODO (StrictEffects) Should we set a marker on the root if it contains strict effects - // so we don't traverse unnecessarily? similar to subtreeFlags but just at the root level. - // Maybe not a big deal since this is DEV only behavior. - setCurrentFiber(fiber); - invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectUnmountInDEV); + var family = resolveFamily(type); - if (hasPassiveEffects) { - invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectUnmountInDEV); - } + if (family === undefined) { + // Check if we're dealing with a real forwardRef. Don't want to crash early. + if ( + type !== null && + type !== undefined && + typeof type.render === "function" + ) { + // ForwardRef is special because its resolved .type is an object, + // but it's possible that we only have its inner render function in the map. + // If that inner render function is different, we'll build a new forwardRef type. + var currentRender = resolveFunctionForHotReloading(type.render); + + if (type.render !== currentRender) { + var syntheticType = { + $$typeof: REACT_FORWARD_REF_TYPE, + render: currentRender + }; + + if (type.displayName !== undefined) { + syntheticType.displayName = type.displayName; + } - invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectMountInDEV); + return syntheticType; + } + } - if (hasPassiveEffects) { - invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectMountInDEV); - } + return type; + } // Use the latest known implementation. - resetCurrentFiber(); -} + return family.current; + } + } + function isCompatibleFamilyForHotReloading(fiber, element) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return false; + } -function invokeEffectsInDev(firstChild, fiberFlags, invokeEffectFn) { - var current = firstChild; - var subtreeRoot = null; + var prevType = fiber.elementType; + var nextType = element.type; // If we got here, we know types aren't === equal. - while (current != null) { - var primarySubtreeFlag = current.subtreeFlags & fiberFlags; + var needsCompareFamilies = false; + var $$typeofNextType = + typeof nextType === "object" && nextType !== null + ? nextType.$$typeof + : null; - if ( - current !== subtreeRoot && - current.child != null && - primarySubtreeFlag !== NoFlags$1 - ) { - current = current.child; - } else { - if ((current.flags & fiberFlags) !== NoFlags$1) { - invokeEffectFn(current); - } + switch (fiber.tag) { + case ClassComponent: { + if (typeof nextType === "function") { + needsCompareFamilies = true; + } - if (current.sibling !== null) { - current = current.sibling; - } else { - current = subtreeRoot = current.return; - } - } - } -} + break; + } -var didWarnStateUpdateForNotYetMountedComponent = null; -function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { - { - if ((executionContext & RenderContext) !== NoContext) { - // We let the other warning about render phase updates deal with this one. - return; - } + case FunctionComponent: { + if (typeof nextType === "function") { + needsCompareFamilies = true; + } else if ($$typeofNextType === REACT_LAZY_TYPE) { + // We don't know the inner type yet. + // We're going to assume that the lazy inner type is stable, + // and so it is sufficient to avoid reconciling it away. + // We're not going to unwrap or actually use the new lazy type. + needsCompareFamilies = true; + } - if (!(fiber.mode & ConcurrentMode)) { - return; - } + break; + } - var tag = fiber.tag; + case ForwardRef: { + if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { + needsCompareFamilies = true; + } else if ($$typeofNextType === REACT_LAZY_TYPE) { + needsCompareFamilies = true; + } - if ( - tag !== IndeterminateComponent && - tag !== HostRoot && - tag !== ClassComponent && - tag !== FunctionComponent && - tag !== ForwardRef && - tag !== MemoComponent && - tag !== SimpleMemoComponent - ) { - // Only warn for user-defined components, not internal ones like Suspense. - return; - } // We show the whole stack but dedupe on the top component's name because - // the problematic code almost always lies inside that component. + break; + } - var componentName = getComponentNameFromFiber(fiber) || "ReactComponent"; + case MemoComponent: + case SimpleMemoComponent: { + if ($$typeofNextType === REACT_MEMO_TYPE) { + // TODO: if it was but can no longer be simple, + // we shouldn't set this. + needsCompareFamilies = true; + } else if ($$typeofNextType === REACT_LAZY_TYPE) { + needsCompareFamilies = true; + } - if (didWarnStateUpdateForNotYetMountedComponent !== null) { - if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) { - return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow + break; + } - didWarnStateUpdateForNotYetMountedComponent.add(componentName); - } else { - didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]); - } + default: + return false; + } // Check if both types have a family and it's the same one. - var previousFiber = current; + if (needsCompareFamilies) { + // Note: memo() and forwardRef() we'll compare outer rather than inner type. + // This means both of them need to be registered to preserve state. + // If we unwrapped and compared the inner types for wrappers instead, + // then we would risk falsely saying two separate memo(Foo) + // calls are equivalent because they wrap the same Foo function. + var prevFamily = resolveFamily(prevType); // $FlowFixMe[not-a-function] found when upgrading Flow - try { - setCurrentFiber(fiber); + if ( + prevFamily !== undefined && + prevFamily === resolveFamily(nextType) + ) { + return true; + } + } - 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." - ); - } finally { - if (previousFiber) { - setCurrentFiber(fiber); - } else { - resetCurrentFiber(); + return false; } } - } -} -var beginWork; - -if (replayFailedUnitOfWorkWithInvokeGuardedCallback) { - var dummyFiber = null; - - beginWork = function (current, unitOfWork, lanes) { - // If a component throws an error, we replay it again in a synchronously - // dispatched event, so that the debugger will treat it as an uncaught - // error See ReactErrorUtils for more information. - // Before entering the begin phase, copy the work-in-progress onto a dummy - // fiber. If beginWork throws, we'll use this to reset the state. - var originalWorkInProgressCopy = assignFiberPropertiesInDEV( - dummyFiber, - unitOfWork - ); + function markFailedErrorBoundaryForHotReloading(fiber) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return; + } - try { - return beginWork$1(current, unitOfWork, lanes); - } catch (originalError) { - if ( - didSuspendOrErrorWhileHydratingDEV() || - originalError === SuspenseException || - originalError === SelectiveHydrationException || - (originalError !== null && - typeof originalError === "object" && - typeof originalError.then === "function") - ) { - // Don't replay promises. - // Don't replay errors if we are hydrating and have already suspended or handled an error - throw originalError; - } // Don't reset current debug fiber, since we're about to work on the - // same fiber again. - // Unwind the failed stack frame + if (typeof WeakSet !== "function") { + return; + } - resetSuspendedWorkLoopOnUnwind(unitOfWork); - unwindInterruptedWork(current, unitOfWork); // Restore the original properties of the fiber. + if (failedBoundaries === null) { + failedBoundaries = new WeakSet(); + } - assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); + failedBoundaries.add(fiber); + } + } + var scheduleRefresh = function (root, update) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return; + } - if (unitOfWork.mode & ProfileMode) { - // Reset the profiler timer. - startProfilerTimer(unitOfWork); - } // Run beginWork again. + var staleFamilies = update.staleFamilies, + updatedFamilies = update.updatedFamilies; + flushPassiveEffects(); + flushSync(function () { + scheduleFibersWithFamiliesRecursively( + root.current, + updatedFamilies, + staleFamilies + ); + }); + } + }; + var scheduleRoot = function (root, element) { + { + if (root.context !== emptyContextObject) { + // Super edge case: root has a legacy _renderSubtree context + // but we don't know the parentComponent so we can't pass it. + // Just ignore. We'll delete this with _renderSubtree code path later. + return; + } - invokeGuardedCallback( - null, - beginWork$1, - null, - current, - unitOfWork, - lanes - ); + flushPassiveEffects(); + flushSync(function () { + updateContainer(element, root, null, null); + }); + } + }; - if (hasCaughtError()) { - var replayError = clearCaughtError(); + function scheduleFibersWithFamiliesRecursively( + fiber, + updatedFamilies, + staleFamilies + ) { + { + var alternate = fiber.alternate, + child = fiber.child, + sibling = fiber.sibling, + tag = fiber.tag, + type = fiber.type; + var candidateType = null; + + switch (tag) { + case FunctionComponent: + case SimpleMemoComponent: + case ClassComponent: + candidateType = type; + break; - if ( - typeof replayError === "object" && - replayError !== null && - replayError._suppressLogging && - typeof originalError === "object" && - originalError !== null && - !originalError._suppressLogging - ) { - // If suppressed, let the flag carry over to the original error which is the one we'll rethrow. - originalError._suppressLogging = true; + case ForwardRef: + candidateType = type.render; + break; } - } // We always throw the original error in case the second render pass is not idempotent. - // This can happen if a memoized function or CommonJS module doesn't throw after first invocation. - - throw originalError; - } - }; -} else { - beginWork = beginWork$1; -} -var didWarnAboutUpdateInRender = false; -var didWarnAboutUpdateInRenderForAnotherComponent; - -{ - didWarnAboutUpdateInRenderForAnotherComponent = new Set(); -} + if (resolveFamily === null) { + throw new Error( + "Expected resolveFamily to be set during hot reload." + ); + } -function warnAboutRenderPhaseUpdatesInDEV(fiber) { - { - if (isRendering) { - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - var renderingComponentName = - (workInProgress && getComponentNameFromFiber(workInProgress)) || - "Unknown"; // Dedupe by the rendering component because it's the one that needs to be fixed. + var needsRender = false; + var needsRemount = false; - var dedupeKey = renderingComponentName; + if (candidateType !== null) { + var family = resolveFamily(candidateType); - if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) { - didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey); - var setStateComponentName = - getComponentNameFromFiber(fiber) || "Unknown"; + if (family !== undefined) { + if (staleFamilies.has(family)) { + needsRemount = true; + } else if (updatedFamilies.has(family)) { + if (tag === ClassComponent) { + needsRemount = true; + } else { + needsRender = true; + } + } + } + } - 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 - ); + if (failedBoundaries !== null) { + if ( + failedBoundaries.has(fiber) || // $FlowFixMe[incompatible-use] found when upgrading Flow + (alternate !== null && failedBoundaries.has(alternate)) + ) { + needsRemount = true; } + } - break; + if (needsRemount) { + fiber._debugNeedsRemount = true; } - case ClassComponent: { - if (!didWarnAboutUpdateInRender) { - error( - "Cannot update during an existing state transition (such as " + - "within `render`). Render methods should be a pure " + - "function of props and state." - ); + if (needsRemount || needsRender) { + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - didWarnAboutUpdateInRender = true; + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); } - - break; } - } - } - } -} - -function restorePendingUpdaters(root, lanes) { - { - if (isDevToolsPresent) { - var memoizedUpdaters = root.memoizedUpdaters; - memoizedUpdaters.forEach(function (schedulingFiber) { - addFiberToLanesMap(root, schedulingFiber, lanes); - }); // This function intentionally does not clear memoized updaters. - // Those may still be relevant to the current commit - // and a future one (e.g. Suspense). - } - } -} -var fakeActCallbackNode = {}; // $FlowFixMe[missing-local-annot] -function scheduleCallback(priorityLevel, callback) { - { - // If we're currently inside an `act` scope, bypass Scheduler and push to - // the `act` queue instead. - var actQueue = ReactCurrentActQueue.current; + if (child !== null && !needsRemount) { + scheduleFibersWithFamiliesRecursively( + child, + updatedFamilies, + staleFamilies + ); + } - if (actQueue !== null) { - actQueue.push(callback); - return fakeActCallbackNode; - } else { - return scheduleCallback$3(priorityLevel, callback); + if (sibling !== null) { + scheduleFibersWithFamiliesRecursively( + sibling, + updatedFamilies, + staleFamilies + ); + } + } } - } -} -function shouldForceFlushFallbacksInDEV() { - // Never force flush in production. This function should get stripped out. - return ReactCurrentActQueue.current !== null; -} - -function warnIfUpdatesNotWrappedWithActDEV(fiber) { - { - if (fiber.mode & ConcurrentMode) { - if (!isConcurrentActEnvironment()) { - // Not in an act environment. No need to warn. - return; - } - } else { - // Legacy mode has additional cases where we suppress a warning. - if (!isLegacyActEnvironment()) { - // Not in an act environment. No need to warn. - return; + var findHostInstancesForRefresh = function (root, families) { + { + var hostInstances = new Set(); + var types = new Set( + families.map(function (family) { + return family.current; + }) + ); + findHostInstancesForMatchingFibersRecursively( + root.current, + types, + hostInstances + ); + return hostInstances; } + }; - if (executionContext !== NoContext) { - // Legacy mode doesn't warn if the update is batched, i.e. - // batchedUpdates or flushSync. - return; - } + function findHostInstancesForMatchingFibersRecursively( + fiber, + types, + hostInstances + ) { + { + var child = fiber.child, + sibling = fiber.sibling, + tag = fiber.tag, + type = fiber.type; + var candidateType = null; + + switch (tag) { + case FunctionComponent: + case SimpleMemoComponent: + case ClassComponent: + candidateType = type; + break; - if ( - fiber.tag !== FunctionComponent && - fiber.tag !== ForwardRef && - fiber.tag !== SimpleMemoComponent - ) { - // For backwards compatibility with pre-hooks code, legacy mode only - // warns for updates that originate from a hook. - return; - } - } + case ForwardRef: + candidateType = type.render; + break; + } - if (ReactCurrentActQueue.current === null) { - var previousFiber = current; + var didMatch = false; - try { - setCurrentFiber(fiber); + if (candidateType !== null) { + if (types.has(candidateType)) { + didMatch = true; + } + } - 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) - ); - } finally { - if (previousFiber) { - setCurrentFiber(fiber); + if (didMatch) { + // We have a match. This only drills down to the closest host components. + // There's no need to search deeper because for the purpose of giving + // visual feedback, "flashing" outermost parent rectangles is sufficient. + findHostInstancesForFiberShallowly(fiber, hostInstances); } else { - resetCurrentFiber(); + // If there's no match, maybe there will be one further down in the child tree. + if (child !== null) { + findHostInstancesForMatchingFibersRecursively( + child, + types, + hostInstances + ); + } + } + + if (sibling !== null) { + findHostInstancesForMatchingFibersRecursively( + sibling, + types, + hostInstances + ); } } } - } -} -function warnIfSuspenseResolutionNotWrappedWithActDEV(root) { - { - if ( - root.tag !== LegacyRoot && - isConcurrentActEnvironment() && - ReactCurrentActQueue.current === null - ) { - 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" - ); - } - } -} + function findHostInstancesForFiberShallowly(fiber, hostInstances) { + { + var foundHostInstances = findChildHostInstancesForFiberShallowly( + fiber, + hostInstances + ); + + if (foundHostInstances) { + return; + } // If we didn't find any host children, fallback to closest host parent. -function setIsRunningInsertionEffect(isRunning) { - { - isRunningInsertionEffect = isRunning; - } -} + var node = fiber; -/* eslint-disable react-internal/prod-error-codes */ -// Used by React Refresh runtime through DevTools Global Hook. + while (true) { + switch (node.tag) { + case HostSingleton: + case HostComponent: + hostInstances.add(node.stateNode); + return; -var resolveFamily = null; -var failedBoundaries = null; -var setRefreshHandler = function (handler) { - { - resolveFamily = handler; - } -}; -function resolveFunctionForHotReloading(type) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return type; - } + case HostPortal: + hostInstances.add(node.stateNode.containerInfo); + return; - var family = resolveFamily(type); + case HostRoot: + hostInstances.add(node.stateNode.containerInfo); + return; + } - if (family === undefined) { - return type; - } // Use the latest known implementation. + if (node.return === null) { + throw new Error("Expected to reach root first."); + } - return family.current; - } -} -function resolveClassForHotReloading(type) { - // No implementation differences. - return resolveFunctionForHotReloading(type); -} -function resolveForwardRefForHotReloading(type) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return type; + node = node.return; + } + } } - var family = resolveFamily(type); + function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { + { + var node = fiber; + var foundHostInstances = false; - if (family === undefined) { - // Check if we're dealing with a real forwardRef. Don't want to crash early. - if ( - type !== null && - type !== undefined && - typeof type.render === "function" - ) { - // ForwardRef is special because its resolved .type is an object, - // but it's possible that we only have its inner render function in the map. - // If that inner render function is different, we'll build a new forwardRef type. - var currentRender = resolveFunctionForHotReloading(type.render); - - if (type.render !== currentRender) { - var syntheticType = { - $$typeof: REACT_FORWARD_REF_TYPE, - render: currentRender - }; + while (true) { + if ( + node.tag === HostComponent || + node.tag === HostHoistable || + false + ) { + // We got a match. + foundHostInstances = true; + hostInstances.add(node.stateNode); // There may still be more, so keep searching. + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } + + if (node === fiber) { + return foundHostInstances; + } - if (type.displayName !== undefined) { - syntheticType.displayName = type.displayName; + while (node.sibling === null) { + if (node.return === null || node.return === fiber) { + return foundHostInstances; + } + + node = node.return; } - return syntheticType; + node.sibling.return = node.return; + node = node.sibling; } } - return type; - } // Use the latest known implementation. - - return family.current; - } -} -function isCompatibleFamilyForHotReloading(fiber, element) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. return false; } - var prevType = fiber.elementType; - var nextType = element.type; // If we got here, we know types aren't === equal. + var hasBadMapPolyfill; - var needsCompareFamilies = false; - var $$typeofNextType = - typeof nextType === "object" && nextType !== null - ? nextType.$$typeof - : null; + { + hasBadMapPolyfill = false; - switch (fiber.tag) { - case ClassComponent: { - if (typeof nextType === "function") { - needsCompareFamilies = true; - } + try { + var nonExtensibleObject = Object.preventExtensions({}); + /* eslint-disable no-new */ + + new Map([[nonExtensibleObject, null]]); + new Set([nonExtensibleObject]); + /* eslint-enable no-new */ + } catch (e) { + // TODO: Consider warning about bad polyfills + hasBadMapPolyfill = true; + } + } + + function FiberNode(tag, pendingProps, key, mode) { + // Instance + this.tag = tag; + this.key = key; + this.elementType = null; + this.type = null; + this.stateNode = null; // Fiber + + this.return = null; + this.child = null; + this.sibling = null; + this.index = 0; + this.ref = null; + this.refCleanup = null; + this.pendingProps = pendingProps; + this.memoizedProps = null; + this.updateQueue = null; + this.memoizedState = null; + this.dependencies = null; + this.mode = mode; // Effects + + this.flags = NoFlags$1; + this.subtreeFlags = NoFlags$1; + this.deletions = null; + this.lanes = NoLanes; + this.childLanes = NoLanes; + this.alternate = null; - break; + { + // Note: The following is done to avoid a v8 performance cliff. + // + // Initializing the fields below to smis and later updating them with + // double values will cause Fibers to end up having separate shapes. + // This behavior/bug has something to do with Object.preventExtension(). + // Fortunately this only impacts DEV builds. + // Unfortunately it makes React unusably slow for some applications. + // To work around this, initialize the fields below with doubles. + // + // Learn more about this here: + // https://github.com/facebook/react/issues/14365 + // https://bugs.chromium.org/p/v8/issues/detail?id=8538 + this.actualDuration = Number.NaN; + this.actualStartTime = Number.NaN; + this.selfBaseDuration = Number.NaN; + this.treeBaseDuration = Number.NaN; // It's okay to replace the initial doubles with smis after initialization. + // This won't trigger the performance cliff mentioned above, + // and it simplifies other profiler code (including DevTools). + + this.actualDuration = 0; + this.actualStartTime = -1; + this.selfBaseDuration = 0; + this.treeBaseDuration = 0; } - case FunctionComponent: { - if (typeof nextType === "function") { - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - // We don't know the inner type yet. - // We're going to assume that the lazy inner type is stable, - // and so it is sufficient to avoid reconciling it away. - // We're not going to unwrap or actually use the new lazy type. - needsCompareFamilies = true; - } + { + // This isn't directly used but is handy for debugging internals: + this._debugSource = null; + this._debugOwner = null; + this._debugNeedsRemount = false; + this._debugHookTypes = null; - break; - } + if ( + !hasBadMapPolyfill && + typeof Object.preventExtensions === "function" + ) { + Object.preventExtensions(this); + } + } + } // This is a constructor function, rather than a POJO constructor, still + // please ensure we do the following: + // 1) Nobody should add any instance methods on this. Instance methods can be + // more difficult to predict when they get optimized and they are almost + // never inlined properly in static compilers. + // 2) Nobody should rely on `instanceof Fiber` for type testing. We should + // always know when it is a fiber. + // 3) We might want to experiment with using numeric keys since they are easier + // to optimize in a non-JIT environment. + // 4) We can easily go from a constructor to a createFiber object literal if that + // is faster. + // 5) It should be easy to port this to a C struct and keep a C implementation + // compatible. + + function createFiber(tag, pendingProps, key, mode) { + // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors + return new FiberNode(tag, pendingProps, key, mode); + } + + function shouldConstruct(Component) { + var prototype = Component.prototype; + return !!(prototype && prototype.isReactComponent); + } + + function isSimpleFunctionComponent(type) { + return ( + typeof type === "function" && + !shouldConstruct(type) && + type.defaultProps === undefined + ); + } + function resolveLazyComponentTag(Component) { + if (typeof Component === "function") { + return shouldConstruct(Component) ? ClassComponent : FunctionComponent; + } else if (Component !== undefined && Component !== null) { + var $$typeof = Component.$$typeof; - case ForwardRef: { - if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - needsCompareFamilies = true; + if ($$typeof === REACT_FORWARD_REF_TYPE) { + return ForwardRef; } - break; + if ($$typeof === REACT_MEMO_TYPE) { + return MemoComponent; + } } - case MemoComponent: - case SimpleMemoComponent: { - if ($$typeofNextType === REACT_MEMO_TYPE) { - // TODO: if it was but can no longer be simple, - // we shouldn't set this. - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - needsCompareFamilies = true; + return IndeterminateComponent; + } // This is used to create an alternate fiber to do work on. + + function createWorkInProgress(current, pendingProps) { + var workInProgress = current.alternate; + + if (workInProgress === null) { + // We use a double buffering pooling technique because we know that we'll + // only ever need at most two versions of a tree. We pool the "other" unused + // node that we're free to reuse. This is lazily created to avoid allocating + // extra objects for things that are never updated. It also allow us to + // reclaim the extra memory if needed. + workInProgress = createFiber( + current.tag, + pendingProps, + current.key, + current.mode + ); + workInProgress.elementType = current.elementType; + workInProgress.type = current.type; + workInProgress.stateNode = current.stateNode; + + { + // DEV-only fields + workInProgress._debugSource = current._debugSource; + workInProgress._debugOwner = current._debugOwner; + workInProgress._debugHookTypes = current._debugHookTypes; } - break; - } + workInProgress.alternate = current; + current.alternate = workInProgress; + } else { + workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type. - default: - return false; - } // Check if both types have a family and it's the same one. + workInProgress.type = current.type; // We already have an alternate. + // Reset the effect tag. - if (needsCompareFamilies) { - // Note: memo() and forwardRef() we'll compare outer rather than inner type. - // This means both of them need to be registered to preserve state. - // If we unwrapped and compared the inner types for wrappers instead, - // then we would risk falsely saying two separate memo(Foo) - // calls are equivalent because they wrap the same Foo function. - var prevFamily = resolveFamily(prevType); // $FlowFixMe[not-a-function] found when upgrading Flow + workInProgress.flags = NoFlags$1; // The effects are no longer valid. - if (prevFamily !== undefined && prevFamily === resolveFamily(nextType)) { - return true; + workInProgress.subtreeFlags = NoFlags$1; + workInProgress.deletions = null; + + { + // We intentionally reset, rather than copy, actualDuration & actualStartTime. + // This prevents time from endlessly accumulating in new commits. + // This has the downside of resetting values for different priority renders, + // But works for yielding (the common case) and should support resuming. + workInProgress.actualDuration = 0; + workInProgress.actualStartTime = -1; + } + } // Reset all effects except static ones. + // Static effects are not specific to a render. + + workInProgress.flags = current.flags & StaticMask; + workInProgress.childLanes = current.childLanes; + workInProgress.lanes = current.lanes; + workInProgress.child = current.child; + workInProgress.memoizedProps = current.memoizedProps; + workInProgress.memoizedState = current.memoizedState; + workInProgress.updateQueue = current.updateQueue; // Clone the dependencies object. This is mutated during the render phase, so + // it cannot be shared with the current fiber. + + var currentDependencies = current.dependencies; + workInProgress.dependencies = + currentDependencies === null + ? null + : { + lanes: currentDependencies.lanes, + firstContext: currentDependencies.firstContext + }; // These will be overridden during the parent's reconciliation + + workInProgress.sibling = current.sibling; + workInProgress.index = current.index; + workInProgress.ref = current.ref; + workInProgress.refCleanup = current.refCleanup; + + { + workInProgress.selfBaseDuration = current.selfBaseDuration; + workInProgress.treeBaseDuration = current.treeBaseDuration; } - } - return false; - } -} -function markFailedErrorBoundaryForHotReloading(fiber) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return; - } + { + workInProgress._debugNeedsRemount = current._debugNeedsRemount; - if (typeof WeakSet !== "function") { - return; - } + switch (workInProgress.tag) { + case IndeterminateComponent: + case FunctionComponent: + case SimpleMemoComponent: + workInProgress.type = resolveFunctionForHotReloading(current.type); + break; - if (failedBoundaries === null) { - failedBoundaries = new WeakSet(); - } + case ClassComponent: + workInProgress.type = resolveClassForHotReloading(current.type); + break; - failedBoundaries.add(fiber); - } -} -var scheduleRefresh = function (root, update) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return; - } - - var staleFamilies = update.staleFamilies, - updatedFamilies = update.updatedFamilies; - flushPassiveEffects(); - flushSync(function () { - scheduleFibersWithFamiliesRecursively( - root.current, - updatedFamilies, - staleFamilies - ); - }); - } -}; -var scheduleRoot = function (root, element) { - { - if (root.context !== emptyContextObject) { - // Super edge case: root has a legacy _renderSubtree context - // but we don't know the parentComponent so we can't pass it. - // Just ignore. We'll delete this with _renderSubtree code path later. - return; - } - - flushPassiveEffects(); - flushSync(function () { - updateContainer(element, root, null, null); - }); - } -}; - -function scheduleFibersWithFamiliesRecursively( - fiber, - updatedFamilies, - staleFamilies -) { - { - var alternate = fiber.alternate, - child = fiber.child, - sibling = fiber.sibling, - tag = fiber.tag, - type = fiber.type; - var candidateType = null; - - switch (tag) { - case FunctionComponent: - case SimpleMemoComponent: - case ClassComponent: - candidateType = type; - break; - - case ForwardRef: - candidateType = type.render; - break; - } - - if (resolveFamily === null) { - throw new Error("Expected resolveFamily to be set during hot reload."); - } - - var needsRender = false; - var needsRemount = false; - - if (candidateType !== null) { - var family = resolveFamily(candidateType); - - if (family !== undefined) { - if (staleFamilies.has(family)) { - needsRemount = true; - } else if (updatedFamilies.has(family)) { - if (tag === ClassComponent) { - needsRemount = true; - } else { - needsRender = true; - } + case ForwardRef: + workInProgress.type = resolveForwardRefForHotReloading( + current.type + ); + break; } } - } - if (failedBoundaries !== null) { - if ( - failedBoundaries.has(fiber) || // $FlowFixMe[incompatible-use] found when upgrading Flow - (alternate !== null && failedBoundaries.has(alternate)) - ) { - needsRemount = true; - } - } + return workInProgress; + } // Used to reuse a Fiber for a second pass. - if (needsRemount) { - fiber._debugNeedsRemount = true; - } + function resetWorkInProgress(workInProgress, renderLanes) { + // This resets the Fiber to what createFiber or createWorkInProgress would + // have set the values to before during the first pass. Ideally this wouldn't + // be necessary but unfortunately many code paths reads from the workInProgress + // when they should be reading from current and writing to workInProgress. + // We assume pendingProps, index, key, ref, return are still untouched to + // avoid doing another reconciliation. + // Reset the effect flags but keep any Placement tags, since that's something + // that child fiber is setting, not the reconciliation. + workInProgress.flags &= StaticMask | Placement; // The effects are no longer valid. - if (needsRemount || needsRender) { - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + var current = workInProgress.alternate; - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } - } + if (current === null) { + // Reset to createFiber's initial values. + workInProgress.childLanes = NoLanes; + workInProgress.lanes = renderLanes; + workInProgress.child = null; + workInProgress.subtreeFlags = NoFlags$1; + workInProgress.memoizedProps = null; + workInProgress.memoizedState = null; + workInProgress.updateQueue = null; + workInProgress.dependencies = null; + workInProgress.stateNode = null; - if (child !== null && !needsRemount) { - scheduleFibersWithFamiliesRecursively( - child, - updatedFamilies, - staleFamilies - ); - } + { + // Note: We don't reset the actualTime counts. It's useful to accumulate + // actual time across multiple render passes. + workInProgress.selfBaseDuration = 0; + workInProgress.treeBaseDuration = 0; + } + } else { + // Reset to the cloned values that createWorkInProgress would've. + workInProgress.childLanes = current.childLanes; + workInProgress.lanes = current.lanes; + workInProgress.child = current.child; + workInProgress.subtreeFlags = NoFlags$1; + workInProgress.deletions = null; + workInProgress.memoizedProps = current.memoizedProps; + workInProgress.memoizedState = current.memoizedState; + workInProgress.updateQueue = current.updateQueue; // Needed because Blocks store data on type. - if (sibling !== null) { - scheduleFibersWithFamiliesRecursively( - sibling, - updatedFamilies, - staleFamilies - ); - } - } -} + workInProgress.type = current.type; // Clone the dependencies object. This is mutated during the render phase, so + // it cannot be shared with the current fiber. -var findHostInstancesForRefresh = function (root, families) { - { - var hostInstances = new Set(); - var types = new Set( - families.map(function (family) { - return family.current; - }) - ); - findHostInstancesForMatchingFibersRecursively( - root.current, - types, - hostInstances - ); - return hostInstances; - } -}; - -function findHostInstancesForMatchingFibersRecursively( - fiber, - types, - hostInstances -) { - { - var child = fiber.child, - sibling = fiber.sibling, - tag = fiber.tag, - type = fiber.type; - var candidateType = null; - - switch (tag) { - case FunctionComponent: - case SimpleMemoComponent: - case ClassComponent: - candidateType = type; - break; - - case ForwardRef: - candidateType = type.render; - break; - } - - var didMatch = false; - - if (candidateType !== null) { - if (types.has(candidateType)) { - didMatch = true; - } - } - - if (didMatch) { - // We have a match. This only drills down to the closest host components. - // There's no need to search deeper because for the purpose of giving - // visual feedback, "flashing" outermost parent rectangles is sufficient. - findHostInstancesForFiberShallowly(fiber, hostInstances); - } else { - // If there's no match, maybe there will be one further down in the child tree. - if (child !== null) { - findHostInstancesForMatchingFibersRecursively( - child, - types, - hostInstances - ); + var currentDependencies = current.dependencies; + workInProgress.dependencies = + currentDependencies === null + ? null + : { + lanes: currentDependencies.lanes, + firstContext: currentDependencies.firstContext + }; + + { + // Note: We don't reset the actualTime counts. It's useful to accumulate + // actual time across multiple render passes. + workInProgress.selfBaseDuration = current.selfBaseDuration; + workInProgress.treeBaseDuration = current.treeBaseDuration; + } } - } - if (sibling !== null) { - findHostInstancesForMatchingFibersRecursively( - sibling, - types, - hostInstances - ); + return workInProgress; } - } -} - -function findHostInstancesForFiberShallowly(fiber, hostInstances) { - { - var foundHostInstances = findChildHostInstancesForFiberShallowly( - fiber, - hostInstances - ); - - if (foundHostInstances) { - return; - } // If we didn't find any host children, fallback to closest host parent. - - var node = fiber; + function createHostRootFiber( + tag, + isStrictMode, + concurrentUpdatesByDefaultOverride + ) { + var mode; - while (true) { - switch (node.tag) { - case HostSingleton: - case HostComponent: - hostInstances.add(node.stateNode); - return; + if (tag === ConcurrentRoot) { + mode = ConcurrentMode; - case HostPortal: - hostInstances.add(node.stateNode.containerInfo); - return; + if (isStrictMode === true || createRootStrictEffectsByDefault) { + mode |= StrictLegacyMode | StrictEffectsMode; + } - case HostRoot: - hostInstances.add(node.stateNode.containerInfo); - return; + if ( + // Only for internal experiments. + concurrentUpdatesByDefaultOverride + ) { + mode |= ConcurrentUpdatesByDefaultMode; + } + } else { + mode = NoMode; } - if (node.return === null) { - throw new Error("Expected to reach root first."); + if (isDevToolsPresent) { + // Always collect profile timings when DevTools are present. + // This enables DevTools to start capturing timing at any point– + // Without some nodes in the tree having empty base times. + mode |= ProfileMode; } - node = node.return; + return createFiber(HostRoot, null, null, mode); } - } -} - -function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { - { - var node = fiber; - var foundHostInstances = false; + function createFiberFromTypeAndProps( + type, // React$ElementType + key, + pendingProps, + source, + owner, + mode, + lanes + ) { + var fiberTag = IndeterminateComponent; // The resolved type is set if we know what the final type will be. I.e. it's not lazy. - while (true) { - if (node.tag === HostComponent || node.tag === HostHoistable || false) { - // We got a match. - foundHostInstances = true; - hostInstances.add(node.stateNode); // There may still be more, so keep searching. - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } + var resolvedType = type; - if (node === fiber) { - return foundHostInstances; - } + if (typeof type === "function") { + if (shouldConstruct(type)) { + fiberTag = ClassComponent; - while (node.sibling === null) { - if (node.return === null || node.return === fiber) { - return foundHostInstances; + { + resolvedType = resolveClassForHotReloading(resolvedType); + } + } else { + { + resolvedType = resolveFunctionForHotReloading(resolvedType); + } } + } else if (typeof type === "string") { + { + fiberTag = HostComponent; + } + } else { + getTag: switch (type) { + case REACT_FRAGMENT_TYPE: + return createFiberFromFragment( + pendingProps.children, + mode, + lanes, + key + ); - node = node.return; - } - - node.sibling.return = node.return; - node = node.sibling; - } - } + case REACT_STRICT_MODE_TYPE: + fiberTag = Mode; + mode |= StrictLegacyMode; - return false; -} + if ((mode & ConcurrentMode) !== NoMode) { + // Strict effects should never run on legacy roots + mode |= StrictEffectsMode; -var hasBadMapPolyfill; + if ( + enableDO_NOT_USE_disableStrictPassiveEffect && + pendingProps.DO_NOT_USE_disableStrictPassiveEffect + ) { + mode |= NoStrictPassiveEffectsMode; + } + } -{ - hasBadMapPolyfill = false; + break; - try { - var nonExtensibleObject = Object.preventExtensions({}); - /* eslint-disable no-new */ + case REACT_PROFILER_TYPE: + return createFiberFromProfiler(pendingProps, mode, lanes, key); - new Map([[nonExtensibleObject, null]]); - new Set([nonExtensibleObject]); - /* eslint-enable no-new */ - } catch (e) { - // TODO: Consider warning about bad polyfills - hasBadMapPolyfill = true; - } -} + case REACT_SUSPENSE_TYPE: + return createFiberFromSuspense(pendingProps, mode, lanes, key); -function FiberNode(tag, pendingProps, key, mode) { - // Instance - this.tag = tag; - this.key = key; - this.elementType = null; - this.type = null; - this.stateNode = null; // Fiber - - this.return = null; - this.child = null; - this.sibling = null; - this.index = 0; - this.ref = null; - this.refCleanup = null; - this.pendingProps = pendingProps; - this.memoizedProps = null; - this.updateQueue = null; - this.memoizedState = null; - this.dependencies = null; - this.mode = mode; // Effects - - this.flags = NoFlags$1; - this.subtreeFlags = NoFlags$1; - this.deletions = null; - this.lanes = NoLanes; - this.childLanes = NoLanes; - this.alternate = null; - - { - // Note: The following is done to avoid a v8 performance cliff. - // - // Initializing the fields below to smis and later updating them with - // double values will cause Fibers to end up having separate shapes. - // This behavior/bug has something to do with Object.preventExtension(). - // Fortunately this only impacts DEV builds. - // Unfortunately it makes React unusably slow for some applications. - // To work around this, initialize the fields below with doubles. - // - // Learn more about this here: - // https://github.com/facebook/react/issues/14365 - // https://bugs.chromium.org/p/v8/issues/detail?id=8538 - this.actualDuration = Number.NaN; - this.actualStartTime = Number.NaN; - this.selfBaseDuration = Number.NaN; - this.treeBaseDuration = Number.NaN; // It's okay to replace the initial doubles with smis after initialization. - // This won't trigger the performance cliff mentioned above, - // and it simplifies other profiler code (including DevTools). - - this.actualDuration = 0; - this.actualStartTime = -1; - this.selfBaseDuration = 0; - this.treeBaseDuration = 0; - } - - { - // This isn't directly used but is handy for debugging internals: - this._debugSource = null; - this._debugOwner = null; - this._debugNeedsRemount = false; - this._debugHookTypes = null; - - if (!hasBadMapPolyfill && typeof Object.preventExtensions === "function") { - Object.preventExtensions(this); - } - } -} // This is a constructor function, rather than a POJO constructor, still -// please ensure we do the following: -// 1) Nobody should add any instance methods on this. Instance methods can be -// more difficult to predict when they get optimized and they are almost -// never inlined properly in static compilers. -// 2) Nobody should rely on `instanceof Fiber` for type testing. We should -// always know when it is a fiber. -// 3) We might want to experiment with using numeric keys since they are easier -// to optimize in a non-JIT environment. -// 4) We can easily go from a constructor to a createFiber object literal if that -// is faster. -// 5) It should be easy to port this to a C struct and keep a C implementation -// compatible. - -function createFiber(tag, pendingProps, key, mode) { - // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors - return new FiberNode(tag, pendingProps, key, mode); -} + case REACT_SUSPENSE_LIST_TYPE: + return createFiberFromSuspenseList(pendingProps, mode, lanes, key); -function shouldConstruct(Component) { - var prototype = Component.prototype; - return !!(prototype && prototype.isReactComponent); -} + case REACT_OFFSCREEN_TYPE: + return createFiberFromOffscreen(pendingProps, mode, lanes, key); -function isSimpleFunctionComponent(type) { - return ( - typeof type === "function" && - !shouldConstruct(type) && - type.defaultProps === undefined - ); -} -function resolveLazyComponentTag(Component) { - if (typeof Component === "function") { - return shouldConstruct(Component) ? ClassComponent : FunctionComponent; - } else if (Component !== undefined && Component !== null) { - var $$typeof = Component.$$typeof; + case REACT_LEGACY_HIDDEN_TYPE: { + return createFiberFromLegacyHidden(pendingProps, mode, lanes, key); + } - if ($$typeof === REACT_FORWARD_REF_TYPE) { - return ForwardRef; - } + // Fall through - if ($$typeof === REACT_MEMO_TYPE) { - return MemoComponent; - } - } + case REACT_SCOPE_TYPE: { + return createFiberFromScope(type, pendingProps, mode, lanes, key); + } - return IndeterminateComponent; -} // This is used to create an alternate fiber to do work on. + // Fall through -function createWorkInProgress(current, pendingProps) { - var workInProgress = current.alternate; + case REACT_CACHE_TYPE: { + return createFiberFromCache(pendingProps, mode, lanes, key); + } - if (workInProgress === null) { - // We use a double buffering pooling technique because we know that we'll - // only ever need at most two versions of a tree. We pool the "other" unused - // node that we're free to reuse. This is lazily created to avoid allocating - // extra objects for things that are never updated. It also allow us to - // reclaim the extra memory if needed. - workInProgress = createFiber( - current.tag, - pendingProps, - current.key, - current.mode - ); - workInProgress.elementType = current.elementType; - workInProgress.type = current.type; - workInProgress.stateNode = current.stateNode; + // Fall through - { - // DEV-only fields - workInProgress._debugSource = current._debugSource; - workInProgress._debugOwner = current._debugOwner; - workInProgress._debugHookTypes = current._debugHookTypes; - } + case REACT_TRACING_MARKER_TYPE: + if (enableTransitionTracing) { + return createFiberFromTracingMarker( + pendingProps, + mode, + lanes, + key + ); + } - workInProgress.alternate = current; - current.alternate = workInProgress; - } else { - workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type. + // Fall through - workInProgress.type = current.type; // We already have an alternate. - // Reset the effect tag. + case REACT_DEBUG_TRACING_MODE_TYPE: + if (enableDebugTracing) { + fiberTag = Mode; + mode |= DebugTracingMode; + break; + } - workInProgress.flags = NoFlags$1; // The effects are no longer valid. + // Fall through - workInProgress.subtreeFlags = NoFlags$1; - workInProgress.deletions = null; + default: { + if (typeof type === "object" && type !== null) { + switch (type.$$typeof) { + case REACT_PROVIDER_TYPE: + fiberTag = ContextProvider; + break getTag; + + case REACT_CONTEXT_TYPE: + // This is a consumer + fiberTag = ContextConsumer; + break getTag; + + case REACT_FORWARD_REF_TYPE: + fiberTag = ForwardRef; + + { + resolvedType = + resolveForwardRefForHotReloading(resolvedType); + } - { - // We intentionally reset, rather than copy, actualDuration & actualStartTime. - // This prevents time from endlessly accumulating in new commits. - // This has the downside of resetting values for different priority renders, - // But works for yielding (the common case) and should support resuming. - workInProgress.actualDuration = 0; - workInProgress.actualStartTime = -1; - } - } // Reset all effects except static ones. - // Static effects are not specific to a render. - - workInProgress.flags = current.flags & StaticMask; - workInProgress.childLanes = current.childLanes; - workInProgress.lanes = current.lanes; - workInProgress.child = current.child; - workInProgress.memoizedProps = current.memoizedProps; - workInProgress.memoizedState = current.memoizedState; - workInProgress.updateQueue = current.updateQueue; // Clone the dependencies object. This is mutated during the render phase, so - // it cannot be shared with the current fiber. - - var currentDependencies = current.dependencies; - workInProgress.dependencies = - currentDependencies === null - ? null - : { - lanes: currentDependencies.lanes, - firstContext: currentDependencies.firstContext - }; // These will be overridden during the parent's reconciliation - - workInProgress.sibling = current.sibling; - workInProgress.index = current.index; - workInProgress.ref = current.ref; - workInProgress.refCleanup = current.refCleanup; - - { - workInProgress.selfBaseDuration = current.selfBaseDuration; - workInProgress.treeBaseDuration = current.treeBaseDuration; - } - - { - workInProgress._debugNeedsRemount = current._debugNeedsRemount; - - switch (workInProgress.tag) { - case IndeterminateComponent: - case FunctionComponent: - case SimpleMemoComponent: - workInProgress.type = resolveFunctionForHotReloading(current.type); - break; - - case ClassComponent: - workInProgress.type = resolveClassForHotReloading(current.type); - break; - - case ForwardRef: - workInProgress.type = resolveForwardRefForHotReloading(current.type); - break; - } - } - - return workInProgress; -} // Used to reuse a Fiber for a second pass. - -function resetWorkInProgress(workInProgress, renderLanes) { - // This resets the Fiber to what createFiber or createWorkInProgress would - // have set the values to before during the first pass. Ideally this wouldn't - // be necessary but unfortunately many code paths reads from the workInProgress - // when they should be reading from current and writing to workInProgress. - // We assume pendingProps, index, key, ref, return are still untouched to - // avoid doing another reconciliation. - // Reset the effect flags but keep any Placement tags, since that's something - // that child fiber is setting, not the reconciliation. - workInProgress.flags &= StaticMask | Placement; // The effects are no longer valid. - - var current = workInProgress.alternate; - - if (current === null) { - // Reset to createFiber's initial values. - workInProgress.childLanes = NoLanes; - workInProgress.lanes = renderLanes; - workInProgress.child = null; - workInProgress.subtreeFlags = NoFlags$1; - workInProgress.memoizedProps = null; - workInProgress.memoizedState = null; - workInProgress.updateQueue = null; - workInProgress.dependencies = null; - workInProgress.stateNode = null; + break getTag; - { - // Note: We don't reset the actualTime counts. It's useful to accumulate - // actual time across multiple render passes. - workInProgress.selfBaseDuration = 0; - workInProgress.treeBaseDuration = 0; - } - } else { - // Reset to the cloned values that createWorkInProgress would've. - workInProgress.childLanes = current.childLanes; - workInProgress.lanes = current.lanes; - workInProgress.child = current.child; - workInProgress.subtreeFlags = NoFlags$1; - workInProgress.deletions = null; - workInProgress.memoizedProps = current.memoizedProps; - workInProgress.memoizedState = current.memoizedState; - workInProgress.updateQueue = current.updateQueue; // Needed because Blocks store data on type. - - workInProgress.type = current.type; // Clone the dependencies object. This is mutated during the render phase, so - // it cannot be shared with the current fiber. - - var currentDependencies = current.dependencies; - workInProgress.dependencies = - currentDependencies === null - ? null - : { - lanes: currentDependencies.lanes, - firstContext: currentDependencies.firstContext - }; + case REACT_MEMO_TYPE: + fiberTag = MemoComponent; + break getTag; - { - // Note: We don't reset the actualTime counts. It's useful to accumulate - // actual time across multiple render passes. - workInProgress.selfBaseDuration = current.selfBaseDuration; - workInProgress.treeBaseDuration = current.treeBaseDuration; - } - } + case REACT_LAZY_TYPE: + fiberTag = LazyComponent; + resolvedType = null; + break getTag; + } + } - return workInProgress; -} -function createHostRootFiber( - tag, - isStrictMode, - concurrentUpdatesByDefaultOverride -) { - var mode; + var info = ""; - if (tag === ConcurrentRoot) { - mode = ConcurrentMode; + { + if ( + type === undefined || + (typeof type === "object" && + type !== null && + Object.keys(type).length === 0) + ) { + 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."; + } - if (isStrictMode === true || createRootStrictEffectsByDefault) { - mode |= StrictLegacyMode | StrictEffectsMode; - } + var ownerName = owner ? getComponentNameFromFiber(owner) : null; - if ( - // Only for internal experiments. - concurrentUpdatesByDefaultOverride - ) { - mode |= ConcurrentUpdatesByDefaultMode; - } - } else { - mode = NoMode; - } + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; + } + } - if (isDevToolsPresent) { - // Always collect profile timings when DevTools are present. - // This enables DevTools to start capturing timing at any point– - // Without some nodes in the tree having empty base times. - mode |= ProfileMode; - } + 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) + ); + } + } + } - return createFiber(HostRoot, null, null, mode); -} -function createFiberFromTypeAndProps( - type, // React$ElementType - key, - pendingProps, - source, - owner, - mode, - lanes -) { - var fiberTag = IndeterminateComponent; // The resolved type is set if we know what the final type will be. I.e. it's not lazy. + var fiber = createFiber(fiberTag, pendingProps, key, mode); + fiber.elementType = type; + fiber.type = resolvedType; + fiber.lanes = lanes; - var resolvedType = type; + { + fiber._debugSource = source; + fiber._debugOwner = owner; + } - if (typeof type === "function") { - if (shouldConstruct(type)) { - fiberTag = ClassComponent; + return fiber; + } + function createFiberFromElement(element, mode, lanes) { + var source = null; + var owner = null; { - resolvedType = resolveClassForHotReloading(resolvedType); + source = element._source; + owner = element._owner; } - } else { + + var type = element.type; + var key = element.key; + var pendingProps = element.props; + var fiber = createFiberFromTypeAndProps( + type, + key, + pendingProps, + source, + owner, + mode, + lanes + ); + { - resolvedType = resolveFunctionForHotReloading(resolvedType); + fiber._debugSource = element._source; + fiber._debugOwner = element._owner; } + + return fiber; } - } else if (typeof type === "string") { - { - fiberTag = HostComponent; + function createFiberFromFragment(elements, mode, lanes, key) { + var fiber = createFiber(Fragment, elements, key, mode); + fiber.lanes = lanes; + return fiber; } - } else { - getTag: switch (type) { - case REACT_FRAGMENT_TYPE: - return createFiberFromFragment(pendingProps.children, mode, lanes, key); - case REACT_STRICT_MODE_TYPE: - fiberTag = Mode; - mode |= StrictLegacyMode; - - if ((mode & ConcurrentMode) !== NoMode) { - // Strict effects should never run on legacy roots - mode |= StrictEffectsMode; + function createFiberFromScope(scope, pendingProps, mode, lanes, key) { + var fiber = createFiber(ScopeComponent, pendingProps, key, mode); + fiber.type = scope; + fiber.elementType = scope; + fiber.lanes = lanes; + return fiber; + } - if ( - enableDO_NOT_USE_disableStrictPassiveEffect && - pendingProps.DO_NOT_USE_disableStrictPassiveEffect - ) { - mode |= NoStrictPassiveEffectsMode; - } + function createFiberFromProfiler(pendingProps, mode, lanes, key) { + { + if (typeof pendingProps.id !== "string") { + error( + 'Profiler must specify an "id" of type `string` as a prop. Received the type `%s` instead.', + typeof pendingProps.id + ); } + } + + var fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode); + fiber.elementType = REACT_PROFILER_TYPE; + fiber.lanes = lanes; + + { + fiber.stateNode = { + effectDuration: 0, + passiveEffectDuration: 0 + }; + } - break; + return fiber; + } + + function createFiberFromSuspense(pendingProps, mode, lanes, key) { + var fiber = createFiber(SuspenseComponent, pendingProps, key, mode); + fiber.elementType = REACT_SUSPENSE_TYPE; + fiber.lanes = lanes; + return fiber; + } + function createFiberFromSuspenseList(pendingProps, mode, lanes, key) { + var fiber = createFiber(SuspenseListComponent, pendingProps, key, mode); + fiber.elementType = REACT_SUSPENSE_LIST_TYPE; + fiber.lanes = lanes; + return fiber; + } + function createFiberFromOffscreen(pendingProps, mode, lanes, key) { + var fiber = createFiber(OffscreenComponent, pendingProps, key, mode); + fiber.elementType = REACT_OFFSCREEN_TYPE; + fiber.lanes = lanes; + var primaryChildInstance = { + _visibility: OffscreenVisible, + _pendingVisibility: OffscreenVisible, + _pendingMarkers: null, + _retryCache: null, + _transitions: null, + _current: null, + detach: function () { + return detachOffscreenInstance(primaryChildInstance); + }, + attach: function () { + return attachOffscreenInstance(primaryChildInstance); + } + }; + fiber.stateNode = primaryChildInstance; + return fiber; + } + function createFiberFromLegacyHidden(pendingProps, mode, lanes, key) { + var fiber = createFiber(LegacyHiddenComponent, pendingProps, key, mode); + fiber.elementType = REACT_LEGACY_HIDDEN_TYPE; + fiber.lanes = lanes; // Adding a stateNode for legacy hidden because it's currently using + // the offscreen implementation, which depends on a state node + + var instance = { + _visibility: OffscreenVisible, + _pendingVisibility: OffscreenVisible, + _pendingMarkers: null, + _transitions: null, + _retryCache: null, + _current: null, + detach: function () { + return detachOffscreenInstance(instance); + }, + attach: function () { + return attachOffscreenInstance(instance); + } + }; + fiber.stateNode = instance; + return fiber; + } + function createFiberFromCache(pendingProps, mode, lanes, key) { + var fiber = createFiber(CacheComponent, pendingProps, key, mode); + fiber.elementType = REACT_CACHE_TYPE; + fiber.lanes = lanes; + return fiber; + } + function createFiberFromTracingMarker(pendingProps, mode, lanes, key) { + var fiber = createFiber(TracingMarkerComponent, pendingProps, key, mode); + fiber.elementType = REACT_TRACING_MARKER_TYPE; + fiber.lanes = lanes; + var tracingMarkerInstance = { + tag: TransitionTracingMarker, + transitions: null, + pendingBoundaries: null, + aborts: null, + name: pendingProps.name + }; + fiber.stateNode = tracingMarkerInstance; + return fiber; + } + function createFiberFromText(content, mode, lanes) { + var fiber = createFiber(HostText, content, null, mode); + fiber.lanes = lanes; + return fiber; + } + function createFiberFromPortal(portal, mode, lanes) { + var pendingProps = portal.children !== null ? portal.children : []; + var fiber = createFiber(HostPortal, pendingProps, portal.key, mode); + fiber.lanes = lanes; + fiber.stateNode = { + containerInfo: portal.containerInfo, + pendingChildren: null, + // Used by persistent updates + implementation: portal.implementation + }; + return fiber; + } // Used for stashing WIP properties to replay failed work in DEV. + + function assignFiberPropertiesInDEV(target, source) { + if (target === null) { + // This Fiber's initial properties will always be overwritten. + // We only use a Fiber to ensure the same hidden class so DEV isn't slow. + target = createFiber(IndeterminateComponent, null, null, NoMode); + } // This is intentionally written as a list of all properties. + // We tried to use Object.assign() instead but this is called in + // the hottest path, and Object.assign() was too slow: + // https://github.com/facebook/react/issues/12502 + // This code is DEV-only so size is not a concern. + + target.tag = source.tag; + target.key = source.key; + target.elementType = source.elementType; + target.type = source.type; + target.stateNode = source.stateNode; + target.return = source.return; + target.child = source.child; + target.sibling = source.sibling; + target.index = source.index; + target.ref = source.ref; + target.refCleanup = source.refCleanup; + target.pendingProps = source.pendingProps; + target.memoizedProps = source.memoizedProps; + target.updateQueue = source.updateQueue; + target.memoizedState = source.memoizedState; + target.dependencies = source.dependencies; + target.mode = source.mode; + target.flags = source.flags; + target.subtreeFlags = source.subtreeFlags; + target.deletions = source.deletions; + target.lanes = source.lanes; + target.childLanes = source.childLanes; + target.alternate = source.alternate; - case REACT_PROFILER_TYPE: - return createFiberFromProfiler(pendingProps, mode, lanes, key); + { + target.actualDuration = source.actualDuration; + target.actualStartTime = source.actualStartTime; + target.selfBaseDuration = source.selfBaseDuration; + target.treeBaseDuration = source.treeBaseDuration; + } - case REACT_SUSPENSE_TYPE: - return createFiberFromSuspense(pendingProps, mode, lanes, key); + target._debugSource = source._debugSource; + target._debugOwner = source._debugOwner; + target._debugNeedsRemount = source._debugNeedsRemount; + target._debugHookTypes = source._debugHookTypes; + return target; + } - case REACT_SUSPENSE_LIST_TYPE: - return createFiberFromSuspenseList(pendingProps, mode, lanes, key); + function FiberRootNode( + containerInfo, // $FlowFixMe[missing-local-annot] + tag, + hydrate, + identifierPrefix, + onRecoverableError, + formState + ) { + this.tag = tag; + this.containerInfo = containerInfo; + this.pendingChildren = null; + this.current = null; + this.pingCache = null; + this.finishedWork = null; + this.timeoutHandle = noTimeout; + this.cancelPendingCommit = null; + this.context = null; + this.pendingContext = null; + this.next = null; + this.callbackNode = null; + this.callbackPriority = NoLane; + this.expirationTimes = createLaneMap(NoTimestamp); + this.pendingLanes = NoLanes; + this.suspendedLanes = NoLanes; + this.pingedLanes = NoLanes; + this.expiredLanes = NoLanes; + this.finishedLanes = NoLanes; + this.errorRecoveryDisabledLanes = NoLanes; + this.shellSuspendCounter = 0; + this.entangledLanes = NoLanes; + this.entanglements = createLaneMap(NoLanes); + this.hiddenUpdates = createLaneMap(null); + this.identifierPrefix = identifierPrefix; + this.onRecoverableError = onRecoverableError; - case REACT_OFFSCREEN_TYPE: - return createFiberFromOffscreen(pendingProps, mode, lanes, key); + { + this.pooledCache = null; + this.pooledCacheLanes = NoLanes; + } - case REACT_LEGACY_HIDDEN_TYPE: { - return createFiberFromLegacyHidden(pendingProps, mode, lanes, key); + { + this.hydrationCallbacks = null; } - // Fall through + this.formState = formState; + this.incompleteTransitions = new Map(); - case REACT_SCOPE_TYPE: { - return createFiberFromScope(type, pendingProps, mode, lanes, key); - } + if (enableTransitionTracing) { + this.transitionCallbacks = null; + var transitionLanesMap = (this.transitionLanes = []); - // Fall through + for (var i = 0; i < TotalLanes; i++) { + transitionLanesMap.push(null); + } + } - case REACT_CACHE_TYPE: { - return createFiberFromCache(pendingProps, mode, lanes, key); + { + this.effectDuration = 0; + this.passiveEffectDuration = 0; } - // Fall through + { + this.memoizedUpdaters = new Set(); + var pendingUpdatersLaneMap = (this.pendingUpdatersLaneMap = []); - case REACT_TRACING_MARKER_TYPE: - if (enableTransitionTracing) { - return createFiberFromTracingMarker(pendingProps, mode, lanes, key); + for (var _i = 0; _i < TotalLanes; _i++) { + pendingUpdatersLaneMap.push(new Set()); } + } - // Fall through + { + switch (tag) { + case ConcurrentRoot: + this._debugRootType = hydrate ? "hydrateRoot()" : "createRoot()"; + break; - case REACT_DEBUG_TRACING_MODE_TYPE: - if (enableDebugTracing) { - fiberTag = Mode; - mode |= DebugTracingMode; - break; + case LegacyRoot: + this._debugRootType = hydrate ? "hydrate()" : "render()"; + break; } + } + } - // Fall through + function createFiberRoot( + containerInfo, + tag, + hydrate, + initialChildren, + hydrationCallbacks, + isStrictMode, + concurrentUpdatesByDefaultOverride, // TODO: We have several of these arguments that are conceptually part of the + // host config, but because they are passed in at runtime, we have to thread + // them through the root constructor. Perhaps we should put them all into a + // single type, like a DynamicHostConfig that is defined by the renderer. + identifierPrefix, + onRecoverableError, + transitionCallbacks, + formState + ) { + // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + var root = new FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError, + formState + ); - default: { - if (typeof type === "object" && type !== null) { - switch (type.$$typeof) { - case REACT_PROVIDER_TYPE: - fiberTag = ContextProvider; - break getTag; + { + root.hydrationCallbacks = hydrationCallbacks; + } - case REACT_CONTEXT_TYPE: - // This is a consumer - fiberTag = ContextConsumer; - break getTag; + if (enableTransitionTracing) { + root.transitionCallbacks = transitionCallbacks; + } // Cyclic construction. This cheats the type system right now because + // stateNode is any. + + var uninitializedFiber = createHostRootFiber( + tag, + isStrictMode, + concurrentUpdatesByDefaultOverride + ); + root.current = uninitializedFiber; + uninitializedFiber.stateNode = root; - case REACT_FORWARD_REF_TYPE: - fiberTag = ForwardRef; + { + var initialCache = createCache(); + retainCache(initialCache); // The pooledCache is a fresh cache instance that is used temporarily + // for newly mounted boundaries during a render. In general, the + // pooledCache is always cleared from the root at the end of a render: + // it is either released when render commits, or moved to an Offscreen + // component if rendering suspends. Because the lifetime of the pooled + // cache is distinct from the main memoizedState.cache, it must be + // retained separately. + + root.pooledCache = initialCache; + retainCache(initialCache); + var initialState = { + element: initialChildren, + isDehydrated: hydrate, + cache: initialCache + }; + uninitializedFiber.memoizedState = initialState; + } - { - resolvedType = resolveForwardRefForHotReloading(resolvedType); - } + initializeUpdateQueue(uninitializedFiber); + return root; + } - break getTag; + // Might add PROFILE later. - case REACT_MEMO_TYPE: - fiberTag = MemoComponent; - break getTag; + var didWarnAboutNestedUpdates; - case REACT_LAZY_TYPE: - fiberTag = LazyComponent; - resolvedType = null; - break getTag; - } - } + { + didWarnAboutNestedUpdates = false; + } - var info = ""; + function getContextForSubtree(parentComponent) { + if (!parentComponent) { + return emptyContextObject; + } - { - if ( - type === undefined || - (typeof type === "object" && - type !== null && - Object.keys(type).length === 0) - ) { - 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."; - } + var fiber = get(parentComponent); + var parentContext = findCurrentUnmaskedContext(fiber); - var ownerName = owner ? getComponentNameFromFiber(owner) : null; + if (fiber.tag === ClassComponent) { + var Component = fiber.type; - if (ownerName) { - info += "\n\nCheck the render method of `" + ownerName + "`."; - } + if (isContextProvider(Component)) { + return processChildContext(fiber, Component, parentContext); } - - 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) - ); } - } - } - - var fiber = createFiber(fiberTag, pendingProps, key, mode); - fiber.elementType = type; - fiber.type = resolvedType; - fiber.lanes = lanes; - { - fiber._debugSource = source; - fiber._debugOwner = owner; - } - - return fiber; -} -function createFiberFromElement(element, mode, lanes) { - var source = null; - var owner = null; - - { - source = element._source; - owner = element._owner; - } - - var type = element.type; - var key = element.key; - var pendingProps = element.props; - var fiber = createFiberFromTypeAndProps( - type, - key, - pendingProps, - source, - owner, - mode, - lanes - ); - - { - fiber._debugSource = element._source; - fiber._debugOwner = element._owner; - } - - return fiber; -} -function createFiberFromFragment(elements, mode, lanes, key) { - var fiber = createFiber(Fragment, elements, key, mode); - fiber.lanes = lanes; - return fiber; -} - -function createFiberFromScope(scope, pendingProps, mode, lanes, key) { - var fiber = createFiber(ScopeComponent, pendingProps, key, mode); - fiber.type = scope; - fiber.elementType = scope; - fiber.lanes = lanes; - return fiber; -} + return parentContext; + } -function createFiberFromProfiler(pendingProps, mode, lanes, key) { - { - if (typeof pendingProps.id !== "string") { - error( - 'Profiler must specify an "id" of type `string` as a prop. Received the type `%s` instead.', - typeof pendingProps.id + function createContainer( + containerInfo, + tag, + hydrationCallbacks, + isStrictMode, + concurrentUpdatesByDefaultOverride, + identifierPrefix, + onRecoverableError, + transitionCallbacks + ) { + var hydrate = false; + var initialChildren = null; + return createFiberRoot( + containerInfo, + tag, + hydrate, + initialChildren, + hydrationCallbacks, + isStrictMode, + concurrentUpdatesByDefaultOverride, + identifierPrefix, + onRecoverableError, + transitionCallbacks, + null ); } - } - - var fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode); - fiber.elementType = REACT_PROFILER_TYPE; - fiber.lanes = lanes; + function updateContainer(element, container, parentComponent, callback) { + { + onScheduleRoot(container, element); + } - { - fiber.stateNode = { - effectDuration: 0, - passiveEffectDuration: 0 - }; - } + var current$1 = container.current; + var lane = requestUpdateLane(current$1); - return fiber; -} + if (enableSchedulingProfiler) { + markRenderScheduled(lane); + } -function createFiberFromSuspense(pendingProps, mode, lanes, key) { - var fiber = createFiber(SuspenseComponent, pendingProps, key, mode); - fiber.elementType = REACT_SUSPENSE_TYPE; - fiber.lanes = lanes; - return fiber; -} -function createFiberFromSuspenseList(pendingProps, mode, lanes, key) { - var fiber = createFiber(SuspenseListComponent, pendingProps, key, mode); - fiber.elementType = REACT_SUSPENSE_LIST_TYPE; - fiber.lanes = lanes; - return fiber; -} -function createFiberFromOffscreen(pendingProps, mode, lanes, key) { - var fiber = createFiber(OffscreenComponent, pendingProps, key, mode); - fiber.elementType = REACT_OFFSCREEN_TYPE; - fiber.lanes = lanes; - var primaryChildInstance = { - _visibility: OffscreenVisible, - _pendingVisibility: OffscreenVisible, - _pendingMarkers: null, - _retryCache: null, - _transitions: null, - _current: null, - detach: function () { - return detachOffscreenInstance(primaryChildInstance); - }, - attach: function () { - return attachOffscreenInstance(primaryChildInstance); - } - }; - fiber.stateNode = primaryChildInstance; - return fiber; -} -function createFiberFromLegacyHidden(pendingProps, mode, lanes, key) { - var fiber = createFiber(LegacyHiddenComponent, pendingProps, key, mode); - fiber.elementType = REACT_LEGACY_HIDDEN_TYPE; - fiber.lanes = lanes; // Adding a stateNode for legacy hidden because it's currently using - // the offscreen implementation, which depends on a state node - - var instance = { - _visibility: OffscreenVisible, - _pendingVisibility: OffscreenVisible, - _pendingMarkers: null, - _transitions: null, - _retryCache: null, - _current: null, - detach: function () { - return detachOffscreenInstance(instance); - }, - attach: function () { - return attachOffscreenInstance(instance); - } - }; - fiber.stateNode = instance; - return fiber; -} -function createFiberFromCache(pendingProps, mode, lanes, key) { - var fiber = createFiber(CacheComponent, pendingProps, key, mode); - fiber.elementType = REACT_CACHE_TYPE; - fiber.lanes = lanes; - return fiber; -} -function createFiberFromTracingMarker(pendingProps, mode, lanes, key) { - var fiber = createFiber(TracingMarkerComponent, pendingProps, key, mode); - fiber.elementType = REACT_TRACING_MARKER_TYPE; - fiber.lanes = lanes; - var tracingMarkerInstance = { - tag: TransitionTracingMarker, - transitions: null, - pendingBoundaries: null, - aborts: null, - name: pendingProps.name - }; - fiber.stateNode = tracingMarkerInstance; - return fiber; -} -function createFiberFromText(content, mode, lanes) { - var fiber = createFiber(HostText, content, null, mode); - fiber.lanes = lanes; - return fiber; -} -function createFiberFromPortal(portal, mode, lanes) { - var pendingProps = portal.children !== null ? portal.children : []; - var fiber = createFiber(HostPortal, pendingProps, portal.key, mode); - fiber.lanes = lanes; - fiber.stateNode = { - containerInfo: portal.containerInfo, - pendingChildren: null, - // Used by persistent updates - implementation: portal.implementation - }; - return fiber; -} // Used for stashing WIP properties to replay failed work in DEV. - -function assignFiberPropertiesInDEV(target, source) { - if (target === null) { - // This Fiber's initial properties will always be overwritten. - // We only use a Fiber to ensure the same hidden class so DEV isn't slow. - target = createFiber(IndeterminateComponent, null, null, NoMode); - } // This is intentionally written as a list of all properties. - // We tried to use Object.assign() instead but this is called in - // the hottest path, and Object.assign() was too slow: - // https://github.com/facebook/react/issues/12502 - // This code is DEV-only so size is not a concern. - - target.tag = source.tag; - target.key = source.key; - target.elementType = source.elementType; - target.type = source.type; - target.stateNode = source.stateNode; - target.return = source.return; - target.child = source.child; - target.sibling = source.sibling; - target.index = source.index; - target.ref = source.ref; - target.refCleanup = source.refCleanup; - target.pendingProps = source.pendingProps; - target.memoizedProps = source.memoizedProps; - target.updateQueue = source.updateQueue; - target.memoizedState = source.memoizedState; - target.dependencies = source.dependencies; - target.mode = source.mode; - target.flags = source.flags; - target.subtreeFlags = source.subtreeFlags; - target.deletions = source.deletions; - target.lanes = source.lanes; - target.childLanes = source.childLanes; - target.alternate = source.alternate; - - { - target.actualDuration = source.actualDuration; - target.actualStartTime = source.actualStartTime; - target.selfBaseDuration = source.selfBaseDuration; - target.treeBaseDuration = source.treeBaseDuration; - } - - target._debugSource = source._debugSource; - target._debugOwner = source._debugOwner; - target._debugNeedsRemount = source._debugNeedsRemount; - target._debugHookTypes = source._debugHookTypes; - return target; -} + var context = getContextForSubtree(parentComponent); -function FiberRootNode( - containerInfo, // $FlowFixMe[missing-local-annot] - tag, - hydrate, - identifierPrefix, - onRecoverableError, - formState -) { - this.tag = tag; - this.containerInfo = containerInfo; - this.pendingChildren = null; - this.current = null; - this.pingCache = null; - this.finishedWork = null; - this.timeoutHandle = noTimeout; - this.cancelPendingCommit = null; - this.context = null; - this.pendingContext = null; - this.next = null; - this.callbackNode = null; - this.callbackPriority = NoLane; - this.expirationTimes = createLaneMap(NoTimestamp); - this.pendingLanes = NoLanes; - this.suspendedLanes = NoLanes; - this.pingedLanes = NoLanes; - this.expiredLanes = NoLanes; - this.finishedLanes = NoLanes; - this.errorRecoveryDisabledLanes = NoLanes; - this.shellSuspendCounter = 0; - this.entangledLanes = NoLanes; - this.entanglements = createLaneMap(NoLanes); - this.hiddenUpdates = createLaneMap(null); - this.identifierPrefix = identifierPrefix; - this.onRecoverableError = onRecoverableError; - - { - this.pooledCache = null; - this.pooledCacheLanes = NoLanes; - } - - { - this.hydrationCallbacks = null; - } - - this.formState = formState; - this.incompleteTransitions = new Map(); - - if (enableTransitionTracing) { - this.transitionCallbacks = null; - var transitionLanesMap = (this.transitionLanes = []); - - for (var i = 0; i < TotalLanes; i++) { - transitionLanesMap.push(null); - } - } - - { - this.effectDuration = 0; - this.passiveEffectDuration = 0; - } - - { - this.memoizedUpdaters = new Set(); - var pendingUpdatersLaneMap = (this.pendingUpdatersLaneMap = []); - - for (var _i = 0; _i < TotalLanes; _i++) { - pendingUpdatersLaneMap.push(new Set()); - } - } - - { - switch (tag) { - case ConcurrentRoot: - this._debugRootType = hydrate ? "hydrateRoot()" : "createRoot()"; - break; - - case LegacyRoot: - this._debugRootType = hydrate ? "hydrate()" : "render()"; - break; - } - } -} + if (container.context === null) { + container.context = context; + } else { + container.pendingContext = context; + } -function createFiberRoot( - containerInfo, - tag, - hydrate, - initialChildren, - hydrationCallbacks, - isStrictMode, - concurrentUpdatesByDefaultOverride, // TODO: We have several of these arguments that are conceptually part of the - // host config, but because they are passed in at runtime, we have to thread - // them through the root constructor. Perhaps we should put them all into a - // single type, like a DynamicHostConfig that is defined by the renderer. - identifierPrefix, - onRecoverableError, - transitionCallbacks, - formState -) { - // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions - var root = new FiberRootNode( - containerInfo, - tag, - hydrate, - identifierPrefix, - onRecoverableError, - formState - ); - - { - root.hydrationCallbacks = hydrationCallbacks; - } - - if (enableTransitionTracing) { - root.transitionCallbacks = transitionCallbacks; - } // Cyclic construction. This cheats the type system right now because - // stateNode is any. - - var uninitializedFiber = createHostRootFiber( - tag, - isStrictMode, - concurrentUpdatesByDefaultOverride - ); - root.current = uninitializedFiber; - uninitializedFiber.stateNode = root; - - { - var initialCache = createCache(); - retainCache(initialCache); // The pooledCache is a fresh cache instance that is used temporarily - // for newly mounted boundaries during a render. In general, the - // pooledCache is always cleared from the root at the end of a render: - // it is either released when render commits, or moved to an Offscreen - // component if rendering suspends. Because the lifetime of the pooled - // cache is distinct from the main memoizedState.cache, it must be - // retained separately. - - root.pooledCache = initialCache; - retainCache(initialCache); - var initialState = { - element: initialChildren, - isDehydrated: hydrate, - cache: initialCache - }; - uninitializedFiber.memoizedState = initialState; - } + { + if (isRendering && current !== null && !didWarnAboutNestedUpdates) { + didWarnAboutNestedUpdates = true; - initializeUpdateQueue(uninitializedFiber); - return root; -} + 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" + ); + } + } -// Might add PROFILE later. + var update = createUpdate(lane); // Caution: React DevTools currently depends on this property + // being called "element". -var didWarnAboutNestedUpdates; + update.payload = { + element: element + }; + callback = callback === undefined ? null : callback; -{ - didWarnAboutNestedUpdates = false; -} + if (callback !== null) { + { + if (typeof callback !== "function") { + error( + "render(...): Expected the last optional `callback` argument to be a " + + "function. Instead received: %s.", + callback + ); + } + } -function getContextForSubtree(parentComponent) { - if (!parentComponent) { - return emptyContextObject; - } + update.callback = callback; + } - var fiber = get(parentComponent); - var parentContext = findCurrentUnmaskedContext(fiber); + var root = enqueueUpdate(current$1, update, lane); - if (fiber.tag === ClassComponent) { - var Component = fiber.type; + if (root !== null) { + scheduleUpdateOnFiber(root, current$1, lane); + entangleTransitions(root, current$1, lane); + } - if (isContextProvider(Component)) { - return processChildContext(fiber, Component, parentContext); + return lane; } - } - return parentContext; -} + var shouldErrorImpl = function (fiber) { + return null; + }; -function createContainer( - containerInfo, - tag, - hydrationCallbacks, - isStrictMode, - concurrentUpdatesByDefaultOverride, - identifierPrefix, - onRecoverableError, - transitionCallbacks -) { - var hydrate = false; - var initialChildren = null; - return createFiberRoot( - containerInfo, - tag, - hydrate, - initialChildren, - hydrationCallbacks, - isStrictMode, - concurrentUpdatesByDefaultOverride, - identifierPrefix, - onRecoverableError, - transitionCallbacks, - null - ); -} -function updateContainer(element, container, parentComponent, callback) { - { - onScheduleRoot(container, element); - } - - var current$1 = container.current; - var lane = requestUpdateLane(current$1); - - if (enableSchedulingProfiler) { - markRenderScheduled(lane); - } - - var context = getContextForSubtree(parentComponent); - - if (container.context === null) { - container.context = context; - } else { - container.pendingContext = context; - } - - { - if (isRendering && current !== null && !didWarnAboutNestedUpdates) { - didWarnAboutNestedUpdates = true; - - 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" - ); + function shouldError(fiber) { + return shouldErrorImpl(fiber); } - } - var update = createUpdate(lane); // Caution: React DevTools currently depends on this property - // being called "element". + var shouldSuspendImpl = function (fiber) { + return false; + }; - update.payload = { - element: element - }; - callback = callback === undefined ? null : callback; + function shouldSuspend(fiber) { + return shouldSuspendImpl(fiber); + } + var overrideHookState = null; + var overrideHookStateDeletePath = null; + var overrideHookStateRenamePath = null; + var overrideProps = null; + var overridePropsDeletePath = null; + var overridePropsRenamePath = null; + var scheduleUpdate = null; + var setErrorHandler = null; + var setSuspenseHandler = null; - if (callback !== null) { { - if (typeof callback !== "function") { - error( - "render(...): Expected the last optional `callback` argument to be a " + - "function. Instead received: %s.", - callback - ); - } - } + var copyWithDeleteImpl = function (obj, path, index) { + var key = path[index]; + var updated = isArray(obj) ? obj.slice() : assign({}, obj); - update.callback = callback; - } + if (index + 1 === path.length) { + if (isArray(updated)) { + updated.splice(key, 1); + } else { + delete updated[key]; + } - var root = enqueueUpdate(current$1, update, lane); + return updated; + } // $FlowFixMe[incompatible-use] number or string is fine here - if (root !== null) { - scheduleUpdateOnFiber(root, current$1, lane); - entangleTransitions(root, current$1, lane); - } + updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); + return updated; + }; - return lane; -} + var copyWithDelete = function (obj, path) { + return copyWithDeleteImpl(obj, path, 0); + }; -var shouldErrorImpl = function (fiber) { - return null; -}; + var copyWithRenameImpl = function (obj, oldPath, newPath, index) { + var oldKey = oldPath[index]; + var updated = isArray(obj) ? obj.slice() : assign({}, obj); -function shouldError(fiber) { - return shouldErrorImpl(fiber); -} + if (index + 1 === oldPath.length) { + var newKey = newPath[index]; // $FlowFixMe[incompatible-use] number or string is fine here -var shouldSuspendImpl = function (fiber) { - return false; -}; + updated[newKey] = updated[oldKey]; -function shouldSuspend(fiber) { - return shouldSuspendImpl(fiber); -} -var overrideHookState = null; -var overrideHookStateDeletePath = null; -var overrideHookStateRenamePath = null; -var overrideProps = null; -var overridePropsDeletePath = null; -var overridePropsRenamePath = null; -var scheduleUpdate = null; -var setErrorHandler = null; -var setSuspenseHandler = null; - -{ - var copyWithDeleteImpl = function (obj, path, index) { - var key = path[index]; - var updated = isArray(obj) ? obj.slice() : assign({}, obj); - - if (index + 1 === path.length) { - if (isArray(updated)) { - updated.splice(key, 1); - } else { - delete updated[key]; - } + if (isArray(updated)) { + updated.splice(oldKey, 1); + } else { + delete updated[oldKey]; + } + } else { + // $FlowFixMe[incompatible-use] number or string is fine here + updated[oldKey] = copyWithRenameImpl( + // $FlowFixMe[incompatible-use] number or string is fine here + obj[oldKey], + oldPath, + newPath, + index + 1 + ); + } - return updated; - } // $FlowFixMe[incompatible-use] number or string is fine here + return updated; + }; - updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); - return updated; - }; + var copyWithRename = function (obj, oldPath, newPath) { + if (oldPath.length !== newPath.length) { + warn("copyWithRename() expects paths of the same length"); - var copyWithDelete = function (obj, path) { - return copyWithDeleteImpl(obj, path, 0); - }; + return; + } else { + for (var i = 0; i < newPath.length - 1; i++) { + if (oldPath[i] !== newPath[i]) { + warn( + "copyWithRename() expects paths to be the same except for the deepest key" + ); - var copyWithRenameImpl = function (obj, oldPath, newPath, index) { - var oldKey = oldPath[index]; - var updated = isArray(obj) ? obj.slice() : assign({}, obj); + return; + } + } + } - if (index + 1 === oldPath.length) { - var newKey = newPath[index]; // $FlowFixMe[incompatible-use] number or string is fine here + return copyWithRenameImpl(obj, oldPath, newPath, 0); + }; - updated[newKey] = updated[oldKey]; + var copyWithSetImpl = function (obj, path, index, value) { + if (index >= path.length) { + return value; + } - if (isArray(updated)) { - updated.splice(oldKey, 1); - } else { - delete updated[oldKey]; - } - } else { - // $FlowFixMe[incompatible-use] number or string is fine here - updated[oldKey] = copyWithRenameImpl( - // $FlowFixMe[incompatible-use] number or string is fine here - obj[oldKey], - oldPath, - newPath, - index + 1 - ); - } + var key = path[index]; + var updated = isArray(obj) ? obj.slice() : assign({}, obj); // $FlowFixMe[incompatible-use] number or string is fine here - return updated; - }; + updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); + return updated; + }; - var copyWithRename = function (obj, oldPath, newPath) { - if (oldPath.length !== newPath.length) { - warn("copyWithRename() expects paths of the same length"); + var copyWithSet = function (obj, path, value) { + return copyWithSetImpl(obj, path, 0, value); + }; - return; - } else { - for (var i = 0; i < newPath.length - 1; i++) { - if (oldPath[i] !== newPath[i]) { - warn( - "copyWithRename() expects paths to be the same except for the deepest key" - ); + var findHook = function (fiber, id) { + // For now, the "id" of stateful hooks is just the stateful hook index. + // This may change in the future with e.g. nested hooks. + var currentHook = fiber.memoizedState; - return; + while (currentHook !== null && id > 0) { + currentHook = currentHook.next; + id--; } - } - } - return copyWithRenameImpl(obj, oldPath, newPath, 0); - }; + return currentHook; + }; // Support DevTools editable values for useState and useReducer. - var copyWithSetImpl = function (obj, path, index, value) { - if (index >= path.length) { - return value; - } + overrideHookState = function (fiber, id, path, value) { + var hook = findHook(fiber, id); - var key = path[index]; - var updated = isArray(obj) ? obj.slice() : assign({}, obj); // $FlowFixMe[incompatible-use] number or string is fine here + if (hook !== null) { + var newState = copyWithSet(hook.memoizedState, path, value); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, + // because there is no update we can add for useReducer hooks that won't trigger an error. + // (There's no appropriate action type for DevTools overrides.) + // As a result though, React will see the scheduled update as a noop and bailout. + // Shallow cloning props works as a workaround for now to bypass the bailout check. - updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); - return updated; - }; + fiber.memoizedProps = assign({}, fiber.memoizedProps); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - var copyWithSet = function (obj, path, value) { - return copyWithSetImpl(obj, path, 0, value); - }; - - var findHook = function (fiber, id) { - // For now, the "id" of stateful hooks is just the stateful hook index. - // This may change in the future with e.g. nested hooks. - var currentHook = fiber.memoizedState; + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + } + }; - while (currentHook !== null && id > 0) { - currentHook = currentHook.next; - id--; - } + overrideHookStateDeletePath = function (fiber, id, path) { + var hook = findHook(fiber, id); - return currentHook; - }; // Support DevTools editable values for useState and useReducer. + if (hook !== null) { + var newState = copyWithDelete(hook.memoizedState, path); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, + // because there is no update we can add for useReducer hooks that won't trigger an error. + // (There's no appropriate action type for DevTools overrides.) + // As a result though, React will see the scheduled update as a noop and bailout. + // Shallow cloning props works as a workaround for now to bypass the bailout check. - overrideHookState = function (fiber, id, path, value) { - var hook = findHook(fiber, id); + fiber.memoizedProps = assign({}, fiber.memoizedProps); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (hook !== null) { - var newState = copyWithSet(hook.memoizedState, path, value); - hook.memoizedState = newState; - hook.baseState = newState; // We aren't actually adding an update to the queue, - // because there is no update we can add for useReducer hooks that won't trigger an error. - // (There's no appropriate action type for DevTools overrides.) - // As a result though, React will see the scheduled update as a noop and bailout. - // Shallow cloning props works as a workaround for now to bypass the bailout check. + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + } + }; - fiber.memoizedProps = assign({}, fiber.memoizedProps); - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + overrideHookStateRenamePath = function (fiber, id, oldPath, newPath) { + var hook = findHook(fiber, id); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } - } - }; + if (hook !== null) { + var newState = copyWithRename(hook.memoizedState, oldPath, newPath); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, + // because there is no update we can add for useReducer hooks that won't trigger an error. + // (There's no appropriate action type for DevTools overrides.) + // As a result though, React will see the scheduled update as a noop and bailout. + // Shallow cloning props works as a workaround for now to bypass the bailout check. - overrideHookStateDeletePath = function (fiber, id, path) { - var hook = findHook(fiber, id); + fiber.memoizedProps = assign({}, fiber.memoizedProps); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (hook !== null) { - var newState = copyWithDelete(hook.memoizedState, path); - hook.memoizedState = newState; - hook.baseState = newState; // We aren't actually adding an update to the queue, - // because there is no update we can add for useReducer hooks that won't trigger an error. - // (There's no appropriate action type for DevTools overrides.) - // As a result though, React will see the scheduled update as a noop and bailout. - // Shallow cloning props works as a workaround for now to bypass the bailout check. + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + } + }; // Support DevTools props for function components, forwardRef, memo, host components, etc. - fiber.memoizedProps = assign({}, fiber.memoizedProps); - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + overrideProps = function (fiber, path, value) { + fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } - } - }; + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } - overrideHookStateRenamePath = function (fiber, id, oldPath, newPath) { - var hook = findHook(fiber, id); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (hook !== null) { - var newState = copyWithRename(hook.memoizedState, oldPath, newPath); - hook.memoizedState = newState; - hook.baseState = newState; // We aren't actually adding an update to the queue, - // because there is no update we can add for useReducer hooks that won't trigger an error. - // (There's no appropriate action type for DevTools overrides.) - // As a result though, React will see the scheduled update as a noop and bailout. - // Shallow cloning props works as a workaround for now to bypass the bailout check. + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + }; - fiber.memoizedProps = assign({}, fiber.memoizedProps); - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + overridePropsDeletePath = function (fiber, path) { + fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } - } - }; // Support DevTools props for function components, forwardRef, memo, host components, etc. + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } - overrideProps = function (fiber, path, value) { - fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (fiber.alternate) { - fiber.alternate.pendingProps = fiber.pendingProps; - } + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + }; - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + overridePropsRenamePath = function (fiber, oldPath, newPath) { + fiber.pendingProps = copyWithRename( + fiber.memoizedProps, + oldPath, + newPath + ); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } - }; + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } - overridePropsDeletePath = function (fiber, path) { - fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (fiber.alternate) { - fiber.alternate.pendingProps = fiber.pendingProps; - } + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + }; - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + scheduleUpdate = function (fiber) { + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } - }; + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + }; - overridePropsRenamePath = function (fiber, oldPath, newPath) { - fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath); + setErrorHandler = function (newShouldErrorImpl) { + shouldErrorImpl = newShouldErrorImpl; + }; - if (fiber.alternate) { - fiber.alternate.pendingProps = fiber.pendingProps; + setSuspenseHandler = function (newShouldSuspendImpl) { + shouldSuspendImpl = newShouldSuspendImpl; + }; } - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + function findHostInstanceByFiber(fiber) { + var hostFiber = findCurrentHostFiber(fiber); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } - }; - - scheduleUpdate = function (fiber) { - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + if (hostFiber === null) { + return null; + } - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); + return hostFiber.stateNode; } - }; - setErrorHandler = function (newShouldErrorImpl) { - shouldErrorImpl = newShouldErrorImpl; - }; - - setSuspenseHandler = function (newShouldSuspendImpl) { - shouldSuspendImpl = newShouldSuspendImpl; - }; -} + function emptyFindFiberByHostInstance(instance) { + return null; + } -function findHostInstanceByFiber(fiber) { - var hostFiber = findCurrentHostFiber(fiber); + function getCurrentFiberForDevTools() { + return current; + } + + function injectIntoDevTools(devToolsConfig) { + var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance; + var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; + return injectInternals({ + bundleType: devToolsConfig.bundleType, + version: devToolsConfig.version, + rendererPackageName: devToolsConfig.rendererPackageName, + rendererConfig: devToolsConfig.rendererConfig, + overrideHookState: overrideHookState, + overrideHookStateDeletePath: overrideHookStateDeletePath, + overrideHookStateRenamePath: overrideHookStateRenamePath, + overrideProps: overrideProps, + overridePropsDeletePath: overridePropsDeletePath, + overridePropsRenamePath: overridePropsRenamePath, + setErrorHandler: setErrorHandler, + setSuspenseHandler: setSuspenseHandler, + scheduleUpdate: scheduleUpdate, + currentDispatcherRef: ReactCurrentDispatcher, + findHostInstanceByFiber: findHostInstanceByFiber, + findFiberByHostInstance: + findFiberByHostInstance || emptyFindFiberByHostInstance, + // React Refresh + findHostInstancesForRefresh: findHostInstancesForRefresh, + scheduleRefresh: scheduleRefresh, + scheduleRoot: scheduleRoot, + setRefreshHandler: setRefreshHandler, + // Enables DevTools to append owner stacks to error messages in DEV mode. + getCurrentFiber: getCurrentFiberForDevTools, + // Enables DevTools to detect reconciler version rather than renderer version + // which may not match for third party renderers. + reconcilerVersion: ReactVersion + }); + } - if (hostFiber === null) { - return null; - } + Mode$1.setCurrent( + // Change to 'art/modes/dom' for easier debugging via SVG + FastNoSideEffects + ); + /** Declarative fill-type objects; API design not finalized */ - return hostFiber.stateNode; -} + var slice = Array.prototype.slice; -function emptyFindFiberByHostInstance(instance) { - return null; -} + var LinearGradient = /*#__PURE__*/ (function () { + function LinearGradient(stops, x1, y1, x2, y2) { + this._args = slice.call(arguments); + } -function getCurrentFiberForDevTools() { - return current; -} + var _proto = LinearGradient.prototype; -function injectIntoDevTools(devToolsConfig) { - var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance; - var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; - return injectInternals({ - bundleType: devToolsConfig.bundleType, - version: devToolsConfig.version, - rendererPackageName: devToolsConfig.rendererPackageName, - rendererConfig: devToolsConfig.rendererConfig, - overrideHookState: overrideHookState, - overrideHookStateDeletePath: overrideHookStateDeletePath, - overrideHookStateRenamePath: overrideHookStateRenamePath, - overrideProps: overrideProps, - overridePropsDeletePath: overridePropsDeletePath, - overridePropsRenamePath: overridePropsRenamePath, - setErrorHandler: setErrorHandler, - setSuspenseHandler: setSuspenseHandler, - scheduleUpdate: scheduleUpdate, - currentDispatcherRef: ReactCurrentDispatcher, - findHostInstanceByFiber: findHostInstanceByFiber, - findFiberByHostInstance: - findFiberByHostInstance || emptyFindFiberByHostInstance, - // React Refresh - findHostInstancesForRefresh: findHostInstancesForRefresh, - scheduleRefresh: scheduleRefresh, - scheduleRoot: scheduleRoot, - setRefreshHandler: setRefreshHandler, - // Enables DevTools to append owner stacks to error messages in DEV mode. - getCurrentFiber: getCurrentFiberForDevTools, - // Enables DevTools to detect reconciler version rather than renderer version - // which may not match for third party renderers. - reconcilerVersion: ReactVersion - }); -} + _proto.applyFill = function applyFill(node) { + node.fillLinear.apply(node, this._args); + }; -Mode$1.setCurrent( - // Change to 'art/modes/dom' for easier debugging via SVG - FastNoSideEffects -); -/** Declarative fill-type objects; API design not finalized */ + return LinearGradient; + })(); -var slice = Array.prototype.slice; + var RadialGradient = /*#__PURE__*/ (function () { + function RadialGradient(stops, fx, fy, rx, ry, cx, cy) { + this._args = slice.call(arguments); + } -var LinearGradient = /*#__PURE__*/ (function () { - function LinearGradient(stops, x1, y1, x2, y2) { - this._args = slice.call(arguments); - } + var _proto2 = RadialGradient.prototype; - var _proto = LinearGradient.prototype; + _proto2.applyFill = function applyFill(node) { + node.fillRadial.apply(node, this._args); + }; - _proto.applyFill = function applyFill(node) { - node.fillLinear.apply(node, this._args); - }; + return RadialGradient; + })(); - return LinearGradient; -})(); + var Pattern = /*#__PURE__*/ (function () { + function Pattern(url, width, height, left, top) { + this._args = slice.call(arguments); + } -var RadialGradient = /*#__PURE__*/ (function () { - function RadialGradient(stops, fx, fy, rx, ry, cx, cy) { - this._args = slice.call(arguments); - } + var _proto3 = Pattern.prototype; - var _proto2 = RadialGradient.prototype; + _proto3.applyFill = function applyFill(node) { + node.fillImage.apply(node, this._args); + }; - _proto2.applyFill = function applyFill(node) { - node.fillRadial.apply(node, this._args); - }; + return Pattern; + })(); + /** React Components */ - return RadialGradient; -})(); + var Surface = /*#__PURE__*/ (function (_React$Component) { + _inheritsLoose(Surface, _React$Component); -var Pattern = /*#__PURE__*/ (function () { - function Pattern(url, width, height, left, top) { - this._args = slice.call(arguments); - } + function Surface() { + return _React$Component.apply(this, arguments) || this; + } - var _proto3 = Pattern.prototype; + var _proto4 = Surface.prototype; - _proto3.applyFill = function applyFill(node) { - node.fillImage.apply(node, this._args); - }; + _proto4.componentDidMount = function componentDidMount() { + var _this$props = this.props, + height = _this$props.height, + width = _this$props.width; + this._surface = Mode$1.Surface(+width, +height, this._tagRef); + this._mountNode = createContainer( + this._surface, + LegacyRoot, + null, + false, + false, + "" + ); + updateContainer(this.props.children, this._mountNode, this); + }; - return Pattern; -})(); -/** React Components */ + _proto4.componentDidUpdate = function componentDidUpdate( + prevProps, + prevState + ) { + var props = this.props; -var Surface = /*#__PURE__*/ (function (_React$Component) { - _inheritsLoose(Surface, _React$Component); + if ( + props.height !== prevProps.height || + props.width !== prevProps.width + ) { + this._surface.resize(+props.width, +props.height); + } - function Surface() { - return _React$Component.apply(this, arguments) || this; - } + updateContainer(this.props.children, this._mountNode, this); - var _proto4 = Surface.prototype; + if (this._surface.render) { + this._surface.render(); + } + }; - _proto4.componentDidMount = function componentDidMount() { - var _this$props = this.props, - height = _this$props.height, - width = _this$props.width; - this._surface = Mode$1.Surface(+width, +height, this._tagRef); - this._mountNode = createContainer( - this._surface, - LegacyRoot, - null, - false, - false, - "" - ); - updateContainer(this.props.children, this._mountNode, this); - }; + _proto4.componentWillUnmount = function componentWillUnmount() { + updateContainer(null, this._mountNode, this); + }; - _proto4.componentDidUpdate = function componentDidUpdate( - prevProps, - prevState - ) { - var props = this.props; + _proto4.render = function render() { + var _this = this; - if (props.height !== prevProps.height || props.width !== prevProps.width) { - this._surface.resize(+props.width, +props.height); - } + // This is going to be a placeholder because we don't know what it will + // actually resolve to because ART may render canvas, vml or svg tags here. + // We only allow a subset of properties since others might conflict with + // ART's properties. + var props = this.props; // TODO: ART's Canvas Mode overrides surface title and cursor - updateContainer(this.props.children, this._mountNode, this); + var Tag = Mode$1.Surface.tagName; + return /*#__PURE__*/ React.createElement(Tag, { + ref: function (ref) { + return (_this._tagRef = ref); + }, + accessKey: props.accessKey, + className: props.className, + draggable: props.draggable, + role: props.role, + style: props.style, + tabIndex: props.tabIndex, + title: props.title + }); + }; - if (this._surface.render) { - this._surface.render(); - } - }; + return Surface; + })(React.Component); - _proto4.componentWillUnmount = function componentWillUnmount() { - updateContainer(null, this._mountNode, this); - }; + var Text = /*#__PURE__*/ (function (_React$Component2) { + _inheritsLoose(Text, _React$Component2); - _proto4.render = function render() { - var _this = this; + function Text(props) { + var _this2; - // This is going to be a placeholder because we don't know what it will - // actually resolve to because ART may render canvas, vml or svg tags here. - // We only allow a subset of properties since others might conflict with - // ART's properties. - var props = this.props; // TODO: ART's Canvas Mode overrides surface title and cursor + _this2 = _React$Component2.call(this, props) || this; // We allow reading these props. Ideally we could expose the Text node as + // ref directly. - var Tag = Mode$1.Surface.tagName; - return /*#__PURE__*/ React.createElement(Tag, { - ref: function (ref) { - return (_this._tagRef = ref); - }, - accessKey: props.accessKey, - className: props.className, - draggable: props.draggable, - role: props.role, - style: props.style, - tabIndex: props.tabIndex, - title: props.title - }); - }; + ["height", "width", "x", "y"].forEach(function (key) { + Object.defineProperty(_assertThisInitialized(_this2), key, { + get: function () { + return this._text ? this._text[key] : undefined; + } + }); + }); + return _this2; + } - return Surface; -})(React.Component); + var _proto5 = Text.prototype; -var Text = /*#__PURE__*/ (function (_React$Component2) { - _inheritsLoose(Text, _React$Component2); + _proto5.render = function render() { + var _this3 = this; - function Text(props) { - var _this2; + // This means you can't have children that render into strings... + var T = TYPES.TEXT; + return /*#__PURE__*/ React.createElement( + T, + _extends({}, this.props, { + ref: function (t) { + return (_this3._text = t); + } + }), + childrenAsString(this.props.children) + ); + }; - _this2 = _React$Component2.call(this, props) || this; // We allow reading these props. Ideally we could expose the Text node as - // ref directly. + return Text; + })(React.Component); - ["height", "width", "x", "y"].forEach(function (key) { - Object.defineProperty(_assertThisInitialized(_this2), key, { - get: function () { - return this._text ? this._text[key] : undefined; - } - }); + injectIntoDevTools({ + findFiberByHostInstance: function () { + return null; + }, + bundleType: 1, + version: ReactVersion, + rendererPackageName: "react-art" }); - return _this2; - } - - var _proto5 = Text.prototype; - - _proto5.render = function render() { - var _this3 = this; - - // This means you can't have children that render into strings... - var T = TYPES.TEXT; - return /*#__PURE__*/ React.createElement( - T, - _extends({}, this.props, { - ref: function (t) { - return (_this3._text = t); - } - }), - childrenAsString(this.props.children) - ); - }; - - return Text; -})(React.Component); - -injectIntoDevTools({ - findFiberByHostInstance: function () { - return null; - }, - bundleType: 1, - version: ReactVersion, - rendererPackageName: "react-art" -}); -/** API */ - -var ClippingRectangle = TYPES.CLIPPING_RECTANGLE; -var Group = TYPES.GROUP; -var Shape = TYPES.SHAPE; -var Path = Mode$1.Path; - -exports.Transform = Transform; -exports.ClippingRectangle = ClippingRectangle; -exports.Group = Group; -exports.LinearGradient = LinearGradient; -exports.Path = Path; -exports.Pattern = Pattern; -exports.RadialGradient = RadialGradient; -exports.Shape = Shape; -exports.Surface = Surface; -exports.Text = Text; - - /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ -if ( - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop === - 'function' -) { - __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error()); -} - + /** API */ + + var ClippingRectangle = TYPES.CLIPPING_RECTANGLE; + var Group = TYPES.GROUP; + var Shape = TYPES.SHAPE; + var Path = Mode$1.Path; + + exports.Transform = Transform; + exports.ClippingRectangle = ClippingRectangle; + exports.Group = Group; + exports.LinearGradient = LinearGradient; + exports.Path = Path; + exports.Pattern = Pattern; + exports.RadialGradient = RadialGradient; + exports.Shape = Shape; + exports.Surface = Surface; + exports.Text = Text; + /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ + if ( + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined" && + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop === + "function" + ) { + __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error()); + } })(); } diff --git a/compiled/facebook-www/ReactART-dev.modern.js b/compiled/facebook-www/ReactART-dev.modern.js index fe31611c7a219..350cdf792092e 100644 --- a/compiled/facebook-www/ReactART-dev.modern.js +++ b/compiled/facebook-www/ReactART-dev.modern.js @@ -1,4 +1,5 @@ /** + * @preserve * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the @@ -10,28822 +11,29318 @@ * @preserve-invariant-messages */ -'use strict'; +"use strict"; if (__DEV__) { - (function() { + (function () { + "use strict"; - 'use strict'; + /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ + if ( + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined" && + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart === + "function" + ) { + __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); + } + var React = require("react"); + var Transform = require("art/core/transform"); + var Mode$1 = require("art/modes/current"); + var Scheduler = require("scheduler"); + var FastNoSideEffects = require("art/modes/fast-noSideEffects"); + + function _extends() { + _extends = + Object.assign || + function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } -/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ -if ( - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart === - 'function' -) { - __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); -} - "use strict"; + return target; + }; -var React = require("react"); -var Transform = require("art/core/transform"); -var Mode$1 = require("art/modes/current"); -var Scheduler = require("scheduler"); -var FastNoSideEffects = require("art/modes/fast-noSideEffects"); + return _extends.apply(this, arguments); + } -function _extends() { - _extends = - Object.assign || - function (target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i]; + function _inheritsLoose(subClass, superClass) { + subClass.prototype = Object.create(superClass.prototype); + subClass.prototype.constructor = subClass; + subClass.__proto__ = superClass; + } - for (var key in source) { - if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError( + "this hasn't been initialised - super() hasn't been called" + ); } - return target; - }; + return self; + } - return _extends.apply(this, arguments); -} + var ReactVersion = "18.3.0-www-modern-54fa9775"; -function _inheritsLoose(subClass, superClass) { - subClass.prototype = Object.create(superClass.prototype); - subClass.prototype.constructor = subClass; - subClass.__proto__ = superClass; -} + var LegacyRoot = 0; + var ConcurrentRoot = 1; -function _assertThisInitialized(self) { - if (self === void 0) { - throw new ReferenceError( - "this hasn't been initialised - super() hasn't been called" - ); - } + // This refers to a WWW module. + var warningWWW = require("warning"); - return self; -} + var suppressWarning = false; + function setSuppressWarning(newSuppressWarning) { + { + suppressWarning = newSuppressWarning; + } + } + function warn(format) { + { + if (!suppressWarning) { + for ( + var _len = arguments.length, + args = new Array(_len > 1 ? _len - 1 : 0), + _key = 1; + _key < _len; + _key++ + ) { + args[_key - 1] = arguments[_key]; + } + + printWarning("warn", format, args); + } + } + } + function error(format) { + { + if (!suppressWarning) { + for ( + var _len2 = arguments.length, + args = new Array(_len2 > 1 ? _len2 - 1 : 0), + _key2 = 1; + _key2 < _len2; + _key2++ + ) { + args[_key2 - 1] = arguments[_key2]; + } -var ReactVersion = "18.3.0-www-modern-073e3c23"; + printWarning("error", format, args); + } + } + } -var LegacyRoot = 0; -var ConcurrentRoot = 1; + function printWarning(level, format, args) { + { + var React = require("react"); -// This refers to a WWW module. -var warningWWW = require("warning"); + var ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. -var suppressWarning = false; -function setSuppressWarning(newSuppressWarning) { - { - suppressWarning = newSuppressWarning; - } -} -function warn(format) { - { - if (!suppressWarning) { - for ( - var _len = arguments.length, - args = new Array(_len > 1 ? _len - 1 : 0), - _key = 1; - _key < _len; - _key++ - ) { - args[_key - 1] = arguments[_key]; - } + if (ReactSharedInternals != null) { + var ReactDebugCurrentFrame = + ReactSharedInternals.ReactDebugCurrentFrame; + var stack = ReactDebugCurrentFrame.getStackAddendum(); - printWarning("warn", format, args); - } - } -} -function error(format) { - { - if (!suppressWarning) { - for ( - var _len2 = arguments.length, - args = new Array(_len2 > 1 ? _len2 - 1 : 0), - _key2 = 1; - _key2 < _len2; - _key2++ - ) { - args[_key2 - 1] = arguments[_key2]; - } + if (stack !== "") { + format += "%s"; + args.push(stack); + } + } // TODO: don't ignore level and pass it down somewhere too. - printWarning("error", format, args); + args.unshift(format); + args.unshift(false); + warningWWW.apply(null, args); + } } - } -} -function printWarning(level, format, args) { - { - var React = require("react"); + var assign = Object.assign; + + /** + * `ReactInstanceMap` maintains a mapping from a public facing stateful + * instance (key) and the internal representation (value). This allows public + * methods to accept the user facing instance as an argument and map them back + * to internal methods. + * + * Note that this module is currently shared and assumed to be stateless. + * If this becomes an actual Map, that will break. + */ + function get(key) { + return key._reactInternals; + } + function set(key, value) { + key._reactInternals = value; + } var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; + + // Re-export dynamic flags from the www version. + var dynamicFeatureFlags = require("ReactFeatureFlags"); + + var replayFailedUnitOfWorkWithInvokeGuardedCallback = + dynamicFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback, + enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, + enableUseRefAccessWarning = dynamicFeatureFlags.enableUseRefAccessWarning, + enableLazyContextPropagation = + dynamicFeatureFlags.enableLazyContextPropagation, + enableUnifiedSyncLane = dynamicFeatureFlags.enableUnifiedSyncLane, + enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, + enableDeferRootSchedulingToMicrotask = + dynamicFeatureFlags.enableDeferRootSchedulingToMicrotask, + enableAsyncActions = dynamicFeatureFlags.enableAsyncActions, + alwaysThrottleRetries = dynamicFeatureFlags.alwaysThrottleRetries, + enableDO_NOT_USE_disableStrictPassiveEffect = + dynamicFeatureFlags.enableDO_NOT_USE_disableStrictPassiveEffect, + disableSchedulerTimeoutInWorkLoop = + dynamicFeatureFlags.disableSchedulerTimeoutInWorkLoop, + enableUseDeferredValueInitialArg = + dynamicFeatureFlags.enableUseDeferredValueInitialArg; // On WWW, true is used for a new modern build. + var enableProfilerTimer = true; + var enableProfilerCommitHooks = true; + var enableProfilerNestedUpdatePhase = true; + var enableProfilerNestedUpdateScheduledHook = + dynamicFeatureFlags.enableProfilerNestedUpdateScheduledHook; + var createRootStrictEffectsByDefault = false; + + var enableSchedulingProfiler = dynamicFeatureFlags.enableSchedulingProfiler; // Note: we'll want to remove this when we to userland implementation. + + var FunctionComponent = 0; + var ClassComponent = 1; + var IndeterminateComponent = 2; // Before we know whether it is function or class + + var HostRoot = 3; // Root of a host tree. Could be nested inside another node. + + var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. + + var HostComponent = 5; + var HostText = 6; + var Fragment = 7; + var Mode = 8; + var ContextConsumer = 9; + var ContextProvider = 10; + var ForwardRef = 11; + var Profiler = 12; + var SuspenseComponent = 13; + var MemoComponent = 14; + var SimpleMemoComponent = 15; + var LazyComponent = 16; + var IncompleteClassComponent = 17; + var DehydratedFragment = 18; + var SuspenseListComponent = 19; + var ScopeComponent = 21; + var OffscreenComponent = 22; + var LegacyHiddenComponent = 23; + var CacheComponent = 24; + var TracingMarkerComponent = 25; + var HostHoistable = 26; + var HostSingleton = 27; + + // ATTENTION + // When adding new symbols to this file, + // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' + // The Symbol used to tag the ReactElement-like types. + var REACT_ELEMENT_TYPE = Symbol.for("react.element"); + var REACT_PORTAL_TYPE = Symbol.for("react.portal"); + var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); + var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); + var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); + var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); + var REACT_CONTEXT_TYPE = Symbol.for("react.context"); + var REACT_SERVER_CONTEXT_TYPE = Symbol.for("react.server_context"); + var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); + var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); + var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); + var REACT_MEMO_TYPE = Symbol.for("react.memo"); + var REACT_LAZY_TYPE = Symbol.for("react.lazy"); + var REACT_SCOPE_TYPE = Symbol.for("react.scope"); + var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); + var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); + var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); + var REACT_CACHE_TYPE = Symbol.for("react.cache"); + var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); + var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel"); + var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; + var FAUX_ITERATOR_SYMBOL = "@@iterator"; + function getIteratorFn(maybeIterable) { + if (maybeIterable === null || typeof maybeIterable !== "object") { + return null; + } - if (ReactSharedInternals != null) { - var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - var stack = ReactDebugCurrentFrame.getStackAddendum(); + var maybeIterator = + (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || + maybeIterable[FAUX_ITERATOR_SYMBOL]; - if (stack !== "") { - format += "%s"; - args.push(stack); + if (typeof maybeIterator === "function") { + return maybeIterator; } - } // TODO: don't ignore level and pass it down somewhere too. - args.unshift(format); - args.unshift(false); - warningWWW.apply(null, args); - } -} + return null; + } -var assign = Object.assign; + function getWrappedName$1(outerType, innerType, wrapperName) { + var displayName = outerType.displayName; -/** - * `ReactInstanceMap` maintains a mapping from a public facing stateful - * instance (key) and the internal representation (value). This allows public - * methods to accept the user facing instance as an argument and map them back - * to internal methods. - * - * Note that this module is currently shared and assumed to be stateless. - * If this becomes an actual Map, that will break. - */ -function get(key) { - return key._reactInternals; -} -function set(key, value) { - key._reactInternals = value; -} + if (displayName) { + return displayName; + } -var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; - -// Re-export dynamic flags from the www version. -var dynamicFeatureFlags = require("ReactFeatureFlags"); - -var replayFailedUnitOfWorkWithInvokeGuardedCallback = - dynamicFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback, - enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, - enableUseRefAccessWarning = dynamicFeatureFlags.enableUseRefAccessWarning, - enableLazyContextPropagation = - dynamicFeatureFlags.enableLazyContextPropagation, - enableUnifiedSyncLane = dynamicFeatureFlags.enableUnifiedSyncLane, - enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, - enableDeferRootSchedulingToMicrotask = - dynamicFeatureFlags.enableDeferRootSchedulingToMicrotask, - enableAsyncActions = dynamicFeatureFlags.enableAsyncActions, - alwaysThrottleRetries = dynamicFeatureFlags.alwaysThrottleRetries, - enableDO_NOT_USE_disableStrictPassiveEffect = - dynamicFeatureFlags.enableDO_NOT_USE_disableStrictPassiveEffect, - disableSchedulerTimeoutInWorkLoop = - dynamicFeatureFlags.disableSchedulerTimeoutInWorkLoop, - enableUseDeferredValueInitialArg = - dynamicFeatureFlags.enableUseDeferredValueInitialArg; // On WWW, true is used for a new modern build. -var enableProfilerTimer = true; -var enableProfilerCommitHooks = true; -var enableProfilerNestedUpdatePhase = true; -var enableProfilerNestedUpdateScheduledHook = - dynamicFeatureFlags.enableProfilerNestedUpdateScheduledHook; -var createRootStrictEffectsByDefault = false; - -var enableSchedulingProfiler = dynamicFeatureFlags.enableSchedulingProfiler; // Note: we'll want to remove this when we to userland implementation. - -var FunctionComponent = 0; -var ClassComponent = 1; -var IndeterminateComponent = 2; // Before we know whether it is function or class - -var HostRoot = 3; // Root of a host tree. Could be nested inside another node. - -var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. - -var HostComponent = 5; -var HostText = 6; -var Fragment = 7; -var Mode = 8; -var ContextConsumer = 9; -var ContextProvider = 10; -var ForwardRef = 11; -var Profiler = 12; -var SuspenseComponent = 13; -var MemoComponent = 14; -var SimpleMemoComponent = 15; -var LazyComponent = 16; -var IncompleteClassComponent = 17; -var DehydratedFragment = 18; -var SuspenseListComponent = 19; -var ScopeComponent = 21; -var OffscreenComponent = 22; -var LegacyHiddenComponent = 23; -var CacheComponent = 24; -var TracingMarkerComponent = 25; -var HostHoistable = 26; -var HostSingleton = 27; - -// ATTENTION -// When adding new symbols to this file, -// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' -// The Symbol used to tag the ReactElement-like types. -var REACT_ELEMENT_TYPE = Symbol.for("react.element"); -var REACT_PORTAL_TYPE = Symbol.for("react.portal"); -var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); -var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); -var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); -var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); -var REACT_CONTEXT_TYPE = Symbol.for("react.context"); -var REACT_SERVER_CONTEXT_TYPE = Symbol.for("react.server_context"); -var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); -var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); -var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); -var REACT_MEMO_TYPE = Symbol.for("react.memo"); -var REACT_LAZY_TYPE = Symbol.for("react.lazy"); -var REACT_SCOPE_TYPE = Symbol.for("react.scope"); -var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); -var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); -var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); -var REACT_CACHE_TYPE = Symbol.for("react.cache"); -var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); -var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel"); -var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; -var FAUX_ITERATOR_SYMBOL = "@@iterator"; -function getIteratorFn(maybeIterable) { - if (maybeIterable === null || typeof maybeIterable !== "object") { - return null; - } - - var maybeIterator = - (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || - maybeIterable[FAUX_ITERATOR_SYMBOL]; - - if (typeof maybeIterator === "function") { - return maybeIterator; - } - - return null; -} + var functionName = innerType.displayName || innerType.name || ""; + return functionName !== "" + ? wrapperName + "(" + functionName + ")" + : wrapperName; + } // Keep in sync with react-reconciler/getComponentNameFromFiber -function getWrappedName$1(outerType, innerType, wrapperName) { - var displayName = outerType.displayName; - - if (displayName) { - return displayName; - } - - var functionName = innerType.displayName || innerType.name || ""; - return functionName !== "" - ? wrapperName + "(" + functionName + ")" - : wrapperName; -} // Keep in sync with react-reconciler/getComponentNameFromFiber - -function getContextName$1(type) { - return type.displayName || "Context"; -} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. - -function getComponentNameFromType(type) { - if (type == null) { - // Host root, text node or just invalid type. - return null; - } - - { - if (typeof type.tag === "number") { - error( - "Received an unexpected object in getComponentNameFromType(). " + - "This is likely a bug in React. Please file an issue." - ); - } - } + function getContextName$1(type) { + return type.displayName || "Context"; + } // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. + + function getComponentNameFromType(type) { + if (type == null) { + // Host root, text node or just invalid type. + return null; + } + + { + if (typeof type.tag === "number") { + error( + "Received an unexpected object in getComponentNameFromType(). " + + "This is likely a bug in React. Please file an issue." + ); + } + } - if (typeof type === "function") { - return type.displayName || type.name || null; - } + if (typeof type === "function") { + return type.displayName || type.name || null; + } - if (typeof type === "string") { - return type; - } + if (typeof type === "string") { + return type; + } - switch (type) { - case REACT_FRAGMENT_TYPE: - return "Fragment"; + switch (type) { + case REACT_FRAGMENT_TYPE: + return "Fragment"; - case REACT_PORTAL_TYPE: - return "Portal"; + case REACT_PORTAL_TYPE: + return "Portal"; - case REACT_PROFILER_TYPE: - return "Profiler"; + case REACT_PROFILER_TYPE: + return "Profiler"; - case REACT_STRICT_MODE_TYPE: - return "StrictMode"; + case REACT_STRICT_MODE_TYPE: + return "StrictMode"; - case REACT_SUSPENSE_TYPE: - return "Suspense"; + case REACT_SUSPENSE_TYPE: + return "Suspense"; - case REACT_SUSPENSE_LIST_TYPE: - return "SuspenseList"; + case REACT_SUSPENSE_LIST_TYPE: + return "SuspenseList"; - case REACT_CACHE_TYPE: { - return "Cache"; - } + case REACT_CACHE_TYPE: { + return "Cache"; + } - // Fall through + // Fall through - case REACT_TRACING_MARKER_TYPE: - if (enableTransitionTracing) { - return "TracingMarker"; + case REACT_TRACING_MARKER_TYPE: + if (enableTransitionTracing) { + return "TracingMarker"; + } } - } - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_CONTEXT_TYPE: - var context = type; - return getContextName$1(context) + ".Consumer"; + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_CONTEXT_TYPE: + var context = type; + return getContextName$1(context) + ".Consumer"; - case REACT_PROVIDER_TYPE: - var provider = type; - return getContextName$1(provider._context) + ".Provider"; + case REACT_PROVIDER_TYPE: + var provider = type; + return getContextName$1(provider._context) + ".Provider"; - case REACT_FORWARD_REF_TYPE: - return getWrappedName$1(type, type.render, "ForwardRef"); + case REACT_FORWARD_REF_TYPE: + return getWrappedName$1(type, type.render, "ForwardRef"); - case REACT_MEMO_TYPE: - var outerName = type.displayName || null; + case REACT_MEMO_TYPE: + var outerName = type.displayName || null; - if (outerName !== null) { - return outerName; - } + if (outerName !== null) { + return outerName; + } - return getComponentNameFromType(type.type) || "Memo"; + return getComponentNameFromType(type.type) || "Memo"; - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - try { - return getComponentNameFromType(init(payload)); - } catch (x) { - return null; + try { + return getComponentNameFromType(init(payload)); + } catch (x) { + return null; + } + } } } - } - } - - return null; -} - -function getWrappedName(outerType, innerType, wrapperName) { - var functionName = innerType.displayName || innerType.name || ""; - return ( - outerType.displayName || - (functionName !== "" ? wrapperName + "(" + functionName + ")" : wrapperName) - ); -} // Keep in sync with shared/getComponentNameFromType - -function getContextName(type) { - return type.displayName || "Context"; -} - -function getComponentNameFromFiber(fiber) { - var tag = fiber.tag, - type = fiber.type; - switch (tag) { - case CacheComponent: - return "Cache"; + return null; + } - case ContextConsumer: - var context = type; - return getContextName(context) + ".Consumer"; + function getWrappedName(outerType, innerType, wrapperName) { + var functionName = innerType.displayName || innerType.name || ""; + return ( + outerType.displayName || + (functionName !== "" + ? wrapperName + "(" + functionName + ")" + : wrapperName) + ); + } // Keep in sync with shared/getComponentNameFromType - case ContextProvider: - var provider = type; - return getContextName(provider._context) + ".Provider"; + function getContextName(type) { + return type.displayName || "Context"; + } - case DehydratedFragment: - return "DehydratedFragment"; + function getComponentNameFromFiber(fiber) { + var tag = fiber.tag, + type = fiber.type; - case ForwardRef: - return getWrappedName(type, type.render, "ForwardRef"); + switch (tag) { + case CacheComponent: + return "Cache"; - case Fragment: - return "Fragment"; + case ContextConsumer: + var context = type; + return getContextName(context) + ".Consumer"; - case HostHoistable: - case HostSingleton: - case HostComponent: - // Host component type is the display name (e.g. "div", "View") - return type; + case ContextProvider: + var provider = type; + return getContextName(provider._context) + ".Provider"; - case HostPortal: - return "Portal"; + case DehydratedFragment: + return "DehydratedFragment"; - case HostRoot: - return "Root"; + case ForwardRef: + return getWrappedName(type, type.render, "ForwardRef"); - case HostText: - return "Text"; + case Fragment: + return "Fragment"; - case LazyComponent: - // Name comes from the type in this case; we don't have a tag. - return getComponentNameFromType(type); + case HostHoistable: + case HostSingleton: + case HostComponent: + // Host component type is the display name (e.g. "div", "View") + return type; - case Mode: - if (type === REACT_STRICT_MODE_TYPE) { - // Don't be less specific than shared/getComponentNameFromType - return "StrictMode"; - } + case HostPortal: + return "Portal"; - return "Mode"; + case HostRoot: + return "Root"; - case OffscreenComponent: - return "Offscreen"; + case HostText: + return "Text"; - case Profiler: - return "Profiler"; + case LazyComponent: + // Name comes from the type in this case; we don't have a tag. + return getComponentNameFromType(type); - case ScopeComponent: - return "Scope"; + case Mode: + if (type === REACT_STRICT_MODE_TYPE) { + // Don't be less specific than shared/getComponentNameFromType + return "StrictMode"; + } - case SuspenseComponent: - return "Suspense"; + return "Mode"; - case SuspenseListComponent: - return "SuspenseList"; + case OffscreenComponent: + return "Offscreen"; - case TracingMarkerComponent: - return "TracingMarker"; - // The display name for this tags come from the user-provided type: + case Profiler: + return "Profiler"; - case ClassComponent: - case FunctionComponent: - case IncompleteClassComponent: - case IndeterminateComponent: - case MemoComponent: - case SimpleMemoComponent: - if (typeof type === "function") { - return type.displayName || type.name || null; - } + case ScopeComponent: + return "Scope"; - if (typeof type === "string") { - return type; - } + case SuspenseComponent: + return "Suspense"; - break; + case SuspenseListComponent: + return "SuspenseList"; - case LegacyHiddenComponent: { - return "LegacyHidden"; - } - } + case TracingMarkerComponent: + return "TracingMarker"; + // The display name for this tags come from the user-provided type: - return null; -} + case ClassComponent: + case FunctionComponent: + case IncompleteClassComponent: + case IndeterminateComponent: + case MemoComponent: + case SimpleMemoComponent: + if (typeof type === "function") { + return type.displayName || type.name || null; + } -var NoFlags$1 = - /* */ - 0; -var PerformedWork = - /* */ - 1; -var Placement = - /* */ - 2; -var DidCapture = - /* */ - 128; -var Hydrating = - /* */ - 4096; // You can change the rest (and add more). - -var Update = - /* */ - 4; -/* Skipped value: 0b0000000000000000000000001000; */ - -var ChildDeletion = - /* */ - 16; -var ContentReset = - /* */ - 32; -var Callback = - /* */ - 64; -/* Used by DidCapture: 0b0000000000000000000010000000; */ - -var ForceClientRender = - /* */ - 256; -var Ref = - /* */ - 512; -var Snapshot = - /* */ - 1024; -var Passive$1 = - /* */ - 2048; -/* Used by Hydrating: 0b0000000000000001000000000000; */ - -var Visibility = - /* */ - 8192; -var StoreConsistency = - /* */ - 16384; // It's OK to reuse these bits because these flags are mutually exclusive for -// different fiber types. We should really be doing this for as many flags as -// possible, because we're about to run out of bits. - -var ScheduleRetry = StoreConsistency; -var ShouldSuspendCommit = Visibility; -var LifecycleEffectMask = - Passive$1 | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit) - -var HostEffectMask = - /* */ - 32767; // These are not really side effects, but we still reuse this field. - -var Incomplete = - /* */ - 32768; -var ShouldCapture = - /* */ - 65536; -var ForceUpdateForLegacySuspense = - /* */ - 131072; -var DidPropagateContext = - /* */ - 262144; -var NeedsPropagation = - /* */ - 524288; -var Forked = - /* */ - 1048576; // Static tags describe aspects of a fiber that are not specific to a render, -// e.g. a fiber uses a passive effect (even if there are no updates on this particular render). -// This enables us to defer more work in the unmount case, -// since we can defer traversing the tree during layout to look for Passive effects, -// and instead rely on the static flag as a signal that there may be cleanup work. - -var RefStatic = - /* */ - 2097152; -var LayoutStatic = - /* */ - 4194304; -var PassiveStatic = - /* */ - 8388608; -var MaySuspendCommit = - /* */ - 16777216; // Flag used to identify newly inserted fibers. It isn't reset after commit unlike `Placement`. - -var PlacementDEV = - /* */ - 33554432; -var MountLayoutDev = - /* */ - 67108864; -var MountPassiveDev = - /* */ - 134217728; // Groups of flags that are used in the commit phase to skip over trees that -// don't contain effects, by checking subtreeFlags. - -var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility - // flag logic (see #20043) - Update | - Snapshot | // createEventHandle needs to visit deleted and hidden trees to - // fire beforeblur - // TODO: Only need to visit Deletions during BeforeMutation phase if an - // element is focused. - (ChildDeletion | Visibility); -var MutationMask = - Placement | - Update | - ChildDeletion | - ContentReset | - Ref | - Hydrating | - Visibility; -var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask - -var PassiveMask = Passive$1 | Visibility | ChildDeletion; // Union of tags that don't get reset on clones. -// This allows certain concepts to persist without recalculating them, -// e.g. whether a subtree contains passive effects or portals. - -var StaticMask = LayoutStatic | PassiveStatic | RefStatic | MaySuspendCommit; - -var ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner; -function getNearestMountedFiber(fiber) { - var node = fiber; - var nearestMounted = fiber; - - if (!fiber.alternate) { - // If there is no alternate, this might be a new tree that isn't inserted - // yet. If it is, then it will have a pending insertion effect on it. - var nextNode = node; - - do { - node = nextNode; - - if ((node.flags & (Placement | Hydrating)) !== NoFlags$1) { - // This is an insertion or in-progress hydration. The nearest possible - // mounted fiber is the parent but we need to continue to figure out - // if that one is still mounted. - nearestMounted = node.return; - } // $FlowFixMe[incompatible-type] we bail out when we get a null - - nextNode = node.return; - } while (nextNode); - } else { - while (node.return) { - node = node.return; - } - } - - if (node.tag === HostRoot) { - // TODO: Check if this was a nested HostRoot when used with - // renderContainerIntoSubtree. - return nearestMounted; - } // If we didn't hit the root, that means that we're in an disconnected tree - // that has been unmounted. - - return null; -} -function isMounted(component) { - { - var owner = ReactCurrentOwner$2.current; + if (typeof type === "string") { + return type; + } - if (owner !== null && owner.tag === ClassComponent) { - var ownerFiber = owner; - var instance = ownerFiber.stateNode; + break; - if (!instance._warnedAboutRefsInRender) { - 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" - ); + case LegacyHiddenComponent: { + return "LegacyHidden"; + } } - instance._warnedAboutRefsInRender = true; + return null; } - } - var fiber = get(component); + var NoFlags$1 = + /* */ + 0; + var PerformedWork = + /* */ + 1; + var Placement = + /* */ + 2; + var DidCapture = + /* */ + 128; + var Hydrating = + /* */ + 4096; // You can change the rest (and add more). + + var Update = + /* */ + 4; + /* Skipped value: 0b0000000000000000000000001000; */ + + var ChildDeletion = + /* */ + 16; + var ContentReset = + /* */ + 32; + var Callback = + /* */ + 64; + /* Used by DidCapture: 0b0000000000000000000010000000; */ + + var ForceClientRender = + /* */ + 256; + var Ref = + /* */ + 512; + var Snapshot = + /* */ + 1024; + var Passive$1 = + /* */ + 2048; + /* Used by Hydrating: 0b0000000000000001000000000000; */ + + var Visibility = + /* */ + 8192; + var StoreConsistency = + /* */ + 16384; // It's OK to reuse these bits because these flags are mutually exclusive for + // different fiber types. We should really be doing this for as many flags as + // possible, because we're about to run out of bits. + + var ScheduleRetry = StoreConsistency; + var ShouldSuspendCommit = Visibility; + var LifecycleEffectMask = + Passive$1 | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit) + + var HostEffectMask = + /* */ + 32767; // These are not really side effects, but we still reuse this field. + + var Incomplete = + /* */ + 32768; + var ShouldCapture = + /* */ + 65536; + var ForceUpdateForLegacySuspense = + /* */ + 131072; + var DidPropagateContext = + /* */ + 262144; + var NeedsPropagation = + /* */ + 524288; + var Forked = + /* */ + 1048576; // Static tags describe aspects of a fiber that are not specific to a render, + // e.g. a fiber uses a passive effect (even if there are no updates on this particular render). + // This enables us to defer more work in the unmount case, + // since we can defer traversing the tree during layout to look for Passive effects, + // and instead rely on the static flag as a signal that there may be cleanup work. + + var RefStatic = + /* */ + 2097152; + var LayoutStatic = + /* */ + 4194304; + var PassiveStatic = + /* */ + 8388608; + var MaySuspendCommit = + /* */ + 16777216; // Flag used to identify newly inserted fibers. It isn't reset after commit unlike `Placement`. + + var PlacementDEV = + /* */ + 33554432; + var MountLayoutDev = + /* */ + 67108864; + var MountPassiveDev = + /* */ + 134217728; // Groups of flags that are used in the commit phase to skip over trees that + // don't contain effects, by checking subtreeFlags. + + var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility + // flag logic (see #20043) + Update | + Snapshot | // createEventHandle needs to visit deleted and hidden trees to + // fire beforeblur + // TODO: Only need to visit Deletions during BeforeMutation phase if an + // element is focused. + (ChildDeletion | Visibility); + var MutationMask = + Placement | + Update | + ChildDeletion | + ContentReset | + Ref | + Hydrating | + Visibility; + var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask + + var PassiveMask = Passive$1 | Visibility | ChildDeletion; // Union of tags that don't get reset on clones. + // This allows certain concepts to persist without recalculating them, + // e.g. whether a subtree contains passive effects or portals. + + var StaticMask = + LayoutStatic | PassiveStatic | RefStatic | MaySuspendCommit; + + var ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner; + function getNearestMountedFiber(fiber) { + var node = fiber; + var nearestMounted = fiber; + + if (!fiber.alternate) { + // If there is no alternate, this might be a new tree that isn't inserted + // yet. If it is, then it will have a pending insertion effect on it. + var nextNode = node; - if (!fiber) { - return false; - } - - return getNearestMountedFiber(fiber) === fiber; -} - -function assertIsMounted(fiber) { - if (getNearestMountedFiber(fiber) !== fiber) { - throw new Error("Unable to find node on an unmounted component."); - } -} + do { + node = nextNode; -function findCurrentFiberUsingSlowPath(fiber) { - var alternate = fiber.alternate; + if ((node.flags & (Placement | Hydrating)) !== NoFlags$1) { + // This is an insertion or in-progress hydration. The nearest possible + // mounted fiber is the parent but we need to continue to figure out + // if that one is still mounted. + nearestMounted = node.return; + } // $FlowFixMe[incompatible-type] we bail out when we get a null - if (!alternate) { - // If there is no alternate, then we only need to check if it is mounted. - var nearestMounted = getNearestMountedFiber(fiber); + nextNode = node.return; + } while (nextNode); + } else { + while (node.return) { + node = node.return; + } + } - if (nearestMounted === null) { - throw new Error("Unable to find node on an unmounted component."); - } + if (node.tag === HostRoot) { + // TODO: Check if this was a nested HostRoot when used with + // renderContainerIntoSubtree. + return nearestMounted; + } // If we didn't hit the root, that means that we're in an disconnected tree + // that has been unmounted. - if (nearestMounted !== fiber) { return null; } + function isMounted(component) { + { + var owner = ReactCurrentOwner$2.current; - return fiber; - } // If we have two possible branches, we'll walk backwards up to the root - // to see what path the root points to. On the way we may hit one of the - // special cases and we'll deal with them. + if (owner !== null && owner.tag === ClassComponent) { + var ownerFiber = owner; + var instance = ownerFiber.stateNode; - var a = fiber; - var b = alternate; + if (!instance._warnedAboutRefsInRender) { + 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" + ); + } - while (true) { - var parentA = a.return; + instance._warnedAboutRefsInRender = true; + } + } - if (parentA === null) { - // We're at the root. - break; - } + var fiber = get(component); - var parentB = parentA.alternate; + if (!fiber) { + return false; + } - if (parentB === null) { - // There is no alternate. This is an unusual case. Currently, it only - // happens when a Suspense component is hidden. An extra fragment fiber - // is inserted in between the Suspense fiber and its children. Skip - // over this extra fragment fiber and proceed to the next parent. - var nextParent = parentA.return; + return getNearestMountedFiber(fiber) === fiber; + } - if (nextParent !== null) { - a = b = nextParent; - continue; - } // If there's no parent, we're at the root. + function assertIsMounted(fiber) { + if (getNearestMountedFiber(fiber) !== fiber) { + throw new Error("Unable to find node on an unmounted component."); + } + } - break; - } // If both copies of the parent fiber point to the same child, we can - // assume that the child is current. This happens when we bailout on low - // priority: the bailed out fiber's child reuses the current child. + function findCurrentFiberUsingSlowPath(fiber) { + var alternate = fiber.alternate; - if (parentA.child === parentB.child) { - var child = parentA.child; + if (!alternate) { + // If there is no alternate, then we only need to check if it is mounted. + var nearestMounted = getNearestMountedFiber(fiber); - while (child) { - if (child === a) { - // We've determined that A is the current branch. - assertIsMounted(parentA); - return fiber; + if (nearestMounted === null) { + throw new Error("Unable to find node on an unmounted component."); } - if (child === b) { - // We've determined that B is the current branch. - assertIsMounted(parentA); - return alternate; + if (nearestMounted !== fiber) { + return null; } - child = child.sibling; - } // We should never have an alternate for any mounting node. So the only - // way this could possibly happen is if this was unmounted, if at all. + return fiber; + } // If we have two possible branches, we'll walk backwards up to the root + // to see what path the root points to. On the way we may hit one of the + // special cases and we'll deal with them. - throw new Error("Unable to find node on an unmounted component."); - } + var a = fiber; + var b = alternate; - if (a.return !== b.return) { - // The return pointer of A and the return pointer of B point to different - // fibers. We assume that return pointers never criss-cross, so A must - // belong to the child set of A.return, and B must belong to the child - // set of B.return. - a = parentA; - b = parentB; - } else { - // The return pointers point to the same fiber. We'll have to use the - // default, slow path: scan the child sets of each parent alternate to see - // which child belongs to which set. - // - // Search parent A's child set - var didFindChild = false; - var _child = parentA.child; + while (true) { + var parentA = a.return; - while (_child) { - if (_child === a) { - didFindChild = true; - a = parentA; - b = parentB; + if (parentA === null) { + // We're at the root. break; } - if (_child === b) { - didFindChild = true; - b = parentA; - a = parentB; - break; - } + var parentB = parentA.alternate; - _child = _child.sibling; - } + if (parentB === null) { + // There is no alternate. This is an unusual case. Currently, it only + // happens when a Suspense component is hidden. An extra fragment fiber + // is inserted in between the Suspense fiber and its children. Skip + // over this extra fragment fiber and proceed to the next parent. + var nextParent = parentA.return; - if (!didFindChild) { - // Search parent B's child set - _child = parentB.child; + if (nextParent !== null) { + a = b = nextParent; + continue; + } // If there's no parent, we're at the root. - while (_child) { - if (_child === a) { - didFindChild = true; - a = parentB; - b = parentA; - break; - } + break; + } // If both copies of the parent fiber point to the same child, we can + // assume that the child is current. This happens when we bailout on low + // priority: the bailed out fiber's child reuses the current child. + + if (parentA.child === parentB.child) { + var child = parentA.child; + + while (child) { + if (child === a) { + // We've determined that A is the current branch. + assertIsMounted(parentA); + return fiber; + } - if (_child === b) { - didFindChild = true; - b = parentB; - a = parentA; - break; - } + if (child === b) { + // We've determined that B is the current branch. + assertIsMounted(parentA); + return alternate; + } - _child = _child.sibling; - } + child = child.sibling; + } // We should never have an alternate for any mounting node. So the only + // way this could possibly happen is if this was unmounted, if at all. - if (!didFindChild) { - 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." - ); + throw new Error("Unable to find node on an unmounted component."); } - } - } - - if (a.alternate !== b) { - 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." - ); - } - } // If the root is not a host container, we're in a disconnected tree. I.e. - // unmounted. - if (a.tag !== HostRoot) { - throw new Error("Unable to find node on an unmounted component."); - } + if (a.return !== b.return) { + // The return pointer of A and the return pointer of B point to different + // fibers. We assume that return pointers never criss-cross, so A must + // belong to the child set of A.return, and B must belong to the child + // set of B.return. + a = parentA; + b = parentB; + } else { + // The return pointers point to the same fiber. We'll have to use the + // default, slow path: scan the child sets of each parent alternate to see + // which child belongs to which set. + // + // Search parent A's child set + var didFindChild = false; + var _child = parentA.child; + + while (_child) { + if (_child === a) { + didFindChild = true; + a = parentA; + b = parentB; + break; + } - if (a.stateNode.current === a) { - // We've determined that A is the current branch. - return fiber; - } // Otherwise B has to be current branch. + if (_child === b) { + didFindChild = true; + b = parentA; + a = parentB; + break; + } - return alternate; -} -function findCurrentHostFiber(parent) { - var currentParent = findCurrentFiberUsingSlowPath(parent); - return currentParent !== null - ? findCurrentHostFiberImpl(currentParent) - : null; -} + _child = _child.sibling; + } -function findCurrentHostFiberImpl(node) { - // Next we'll drill down this component to find the first HostComponent/Text. - var tag = node.tag; + if (!didFindChild) { + // Search parent B's child set + _child = parentB.child; - if ( - tag === HostComponent || - tag === HostHoistable || - tag === HostSingleton || - tag === HostText - ) { - return node; - } + while (_child) { + if (_child === a) { + didFindChild = true; + a = parentB; + b = parentA; + break; + } - var child = node.child; + if (_child === b) { + didFindChild = true; + b = parentB; + a = parentA; + break; + } - while (child !== null) { - var match = findCurrentHostFiberImpl(child); + _child = _child.sibling; + } - if (match !== null) { - return match; - } + if (!didFindChild) { + 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." + ); + } + } + } - child = child.sibling; - } + if (a.alternate !== b) { + 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." + ); + } + } // If the root is not a host container, we're in a disconnected tree. I.e. + // unmounted. - return null; -} + if (a.tag !== HostRoot) { + throw new Error("Unable to find node on an unmounted component."); + } -function isFiberSuspenseAndTimedOut(fiber) { - var memoizedState = fiber.memoizedState; - return ( - fiber.tag === SuspenseComponent && - memoizedState !== null && - memoizedState.dehydrated === null - ); -} -function doesFiberContain(parentFiber, childFiber) { - var node = childFiber; - var parentFiberAlternate = parentFiber.alternate; + if (a.stateNode.current === a) { + // We've determined that A is the current branch. + return fiber; + } // Otherwise B has to be current branch. - while (node !== null) { - if (node === parentFiber || node === parentFiberAlternate) { - return true; + return alternate; + } + function findCurrentHostFiber(parent) { + var currentParent = findCurrentFiberUsingSlowPath(parent); + return currentParent !== null + ? findCurrentHostFiberImpl(currentParent) + : null; } - node = node.return; - } + function findCurrentHostFiberImpl(node) { + // Next we'll drill down this component to find the first HostComponent/Text. + var tag = node.tag; - return false; -} + if ( + tag === HostComponent || + tag === HostHoistable || + tag === HostSingleton || + tag === HostText + ) { + return node; + } -var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare + var child = node.child; -function isArray(a) { - return isArrayImpl(a); -} + while (child !== null) { + var match = findCurrentHostFiberImpl(child); -var TYPES = { - CLIPPING_RECTANGLE: "ClippingRectangle", - GROUP: "Group", - SHAPE: "Shape", - TEXT: "Text" -}; -var EVENT_TYPES = { - onClick: "click", - onMouseMove: "mousemove", - onMouseOver: "mouseover", - onMouseOut: "mouseout", - onMouseUp: "mouseup", - onMouseDown: "mousedown" -}; -function childrenAsString(children) { - if (!children) { - return ""; - } else if (typeof children === "string") { - return children; - } else if (children.length) { - return children.join(""); - } else { - return ""; - } -} + if (match !== null) { + return match; + } -// This module only exists as an ESM wrapper around the external CommonJS -var scheduleCallback$3 = Scheduler.unstable_scheduleCallback; -var cancelCallback$1 = Scheduler.unstable_cancelCallback; -var shouldYield = Scheduler.unstable_shouldYield; -var requestPaint = Scheduler.unstable_requestPaint; -var now$1 = Scheduler.unstable_now; -var ImmediatePriority = Scheduler.unstable_ImmediatePriority; -var UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; -var NormalPriority$1 = Scheduler.unstable_NormalPriority; -var IdlePriority = Scheduler.unstable_IdlePriority; // this doesn't actually exist on the scheduler, but it *does* -// on scheduler/unstable_mock, which we'll need for internal testing - -var log$2 = Scheduler.log; -var unstable_setDisableYieldValue = Scheduler.unstable_setDisableYieldValue; - -// Helpers to patch console.logs to avoid logging during side-effect free -// replaying on render function. This currently only patches the object -// lazily which won't cover if the log function was extracted eagerly. -// We could also eagerly patch the method. -var disabledDepth = 0; -var prevLog; -var prevInfo; -var prevWarn; -var prevError; -var prevGroup; -var prevGroupCollapsed; -var prevGroupEnd; - -function disabledLog() {} - -disabledLog.__reactDisabledLog = true; -function disableLogs() { - { - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - prevLog = console.log; - prevInfo = console.info; - prevWarn = console.warn; - prevError = console.error; - prevGroup = console.group; - prevGroupCollapsed = console.groupCollapsed; - prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 - - var props = { - configurable: true, - enumerable: true, - value: disabledLog, - writable: true - }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. - - Object.defineProperties(console, { - info: props, - log: props, - warn: props, - error: props, - group: props, - groupCollapsed: props, - groupEnd: props - }); - /* eslint-enable react-internal/no-production-logging */ - } + child = child.sibling; + } - disabledDepth++; - } -} -function reenableLogs() { - { - disabledDepth--; - - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - var props = { - configurable: true, - enumerable: true, - writable: true - }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. - - Object.defineProperties(console, { - log: assign({}, props, { - value: prevLog - }), - info: assign({}, props, { - value: prevInfo - }), - warn: assign({}, props, { - value: prevWarn - }), - error: assign({}, props, { - value: prevError - }), - group: assign({}, props, { - value: prevGroup - }), - groupCollapsed: assign({}, props, { - value: prevGroupCollapsed - }), - groupEnd: assign({}, props, { - value: prevGroupEnd - }) - }); - /* eslint-enable react-internal/no-production-logging */ + return null; } - if (disabledDepth < 0) { - error( - "disabledDepth fell below zero. " + - "This is a bug in React. Please file an issue." + function isFiberSuspenseAndTimedOut(fiber) { + var memoizedState = fiber.memoizedState; + return ( + fiber.tag === SuspenseComponent && + memoizedState !== null && + memoizedState.dehydrated === null ); } - } -} + function doesFiberContain(parentFiber, childFiber) { + var node = childFiber; + var parentFiberAlternate = parentFiber.alternate; -var rendererID = null; -var injectedHook = null; -var injectedProfilingHooks = null; -var hasLoggedError = false; -var isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined"; -function injectInternals(internals) { - if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { - // No DevTools - return false; - } - - var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - - if (hook.isDisabled) { - // This isn't a real property on the hook, but it can be set to opt out - // of DevTools integration and associated warnings and logs. - // https://github.com/facebook/react/issues/3877 - return true; - } - - if (!hook.supportsFiber) { - { - 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" - ); - } // DevTools exists, even though it doesn't support Fiber. - - return true; - } - - try { - if (enableSchedulingProfiler) { - // Conditionally inject these hooks only if Timeline profiler is supported by this build. - // This gives DevTools a way to feature detect that isn't tied to version number - // (since profiling and timeline are controlled by different feature flags). - internals = assign({}, internals, { - getLaneLabelMap: getLaneLabelMap, - injectProfilingHooks: injectProfilingHooks - }); - } + while (node !== null) { + if (node === parentFiber || node === parentFiberAlternate) { + return true; + } - rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. + node = node.return; + } - injectedHook = hook; - } catch (err) { - // Catch all errors because it is unsafe to throw during initialization. - { - error("React instrumentation encountered an error: %s.", err); + return false; } - } - if (hook.checkDCE) { - // This is the real DevTools. - return true; - } else { - // This is likely a hook installed by Fast Refresh runtime. - return false; - } -} -function onScheduleRoot(root, children) { - { - if ( - injectedHook && - typeof injectedHook.onScheduleFiberRoot === "function" - ) { - try { - injectedHook.onScheduleFiberRoot(rendererID, root, children); - } catch (err) { - if (!hasLoggedError) { - hasLoggedError = true; + var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare - error("React instrumentation encountered an error: %s", err); - } - } + function isArray(a) { + return isArrayImpl(a); } - } -} -function onCommitRoot(root, eventPriority) { - if (injectedHook && typeof injectedHook.onCommitFiberRoot === "function") { - try { - var didError = (root.current.flags & DidCapture) === DidCapture; - if (enableProfilerTimer) { - var schedulerPriority; + var TYPES = { + CLIPPING_RECTANGLE: "ClippingRectangle", + GROUP: "Group", + SHAPE: "Shape", + TEXT: "Text" + }; + var EVENT_TYPES = { + onClick: "click", + onMouseMove: "mousemove", + onMouseOver: "mouseover", + onMouseOut: "mouseout", + onMouseUp: "mouseup", + onMouseDown: "mousedown" + }; + function childrenAsString(children) { + if (!children) { + return ""; + } else if (typeof children === "string") { + return children; + } else if (children.length) { + return children.join(""); + } else { + return ""; + } + } + + // This module only exists as an ESM wrapper around the external CommonJS + var scheduleCallback$3 = Scheduler.unstable_scheduleCallback; + var cancelCallback$1 = Scheduler.unstable_cancelCallback; + var shouldYield = Scheduler.unstable_shouldYield; + var requestPaint = Scheduler.unstable_requestPaint; + var now$1 = Scheduler.unstable_now; + var ImmediatePriority = Scheduler.unstable_ImmediatePriority; + var UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; + var NormalPriority$1 = Scheduler.unstable_NormalPriority; + var IdlePriority = Scheduler.unstable_IdlePriority; // this doesn't actually exist on the scheduler, but it *does* + // on scheduler/unstable_mock, which we'll need for internal testing + + var log$2 = Scheduler.log; + var unstable_setDisableYieldValue = Scheduler.unstable_setDisableYieldValue; + + // Helpers to patch console.logs to avoid logging during side-effect free + // replaying on render function. This currently only patches the object + // lazily which won't cover if the log function was extracted eagerly. + // We could also eagerly patch the method. + var disabledDepth = 0; + var prevLog; + var prevInfo; + var prevWarn; + var prevError; + var prevGroup; + var prevGroupCollapsed; + var prevGroupEnd; + + function disabledLog() {} + + disabledLog.__reactDisabledLog = true; + function disableLogs() { + { + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + prevLog = console.log; + prevInfo = console.info; + prevWarn = console.warn; + prevError = console.error; + prevGroup = console.group; + prevGroupCollapsed = console.groupCollapsed; + prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 + + var props = { + configurable: true, + enumerable: true, + value: disabledLog, + writable: true + }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. + + Object.defineProperties(console, { + info: props, + log: props, + warn: props, + error: props, + group: props, + groupCollapsed: props, + groupEnd: props + }); + /* eslint-enable react-internal/no-production-logging */ + } - switch (eventPriority) { - case DiscreteEventPriority: - schedulerPriority = ImmediatePriority; - break; + disabledDepth++; + } + } + function reenableLogs() { + { + disabledDepth--; + + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + var props = { + configurable: true, + enumerable: true, + writable: true + }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. + + Object.defineProperties(console, { + log: assign({}, props, { + value: prevLog + }), + info: assign({}, props, { + value: prevInfo + }), + warn: assign({}, props, { + value: prevWarn + }), + error: assign({}, props, { + value: prevError + }), + group: assign({}, props, { + value: prevGroup + }), + groupCollapsed: assign({}, props, { + value: prevGroupCollapsed + }), + groupEnd: assign({}, props, { + value: prevGroupEnd + }) + }); + /* eslint-enable react-internal/no-production-logging */ + } - case ContinuousEventPriority: - schedulerPriority = UserBlockingPriority; - break; + if (disabledDepth < 0) { + error( + "disabledDepth fell below zero. " + + "This is a bug in React. Please file an issue." + ); + } + } + } - case DefaultEventPriority: - schedulerPriority = NormalPriority$1; - break; + var rendererID = null; + var injectedHook = null; + var injectedProfilingHooks = null; + var hasLoggedError = false; + var isDevToolsPresent = + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined"; + function injectInternals(internals) { + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { + // No DevTools + return false; + } - case IdleEventPriority: - schedulerPriority = IdlePriority; - break; + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - default: - schedulerPriority = NormalPriority$1; - break; + if (hook.isDisabled) { + // This isn't a real property on the hook, but it can be set to opt out + // of DevTools integration and associated warnings and logs. + // https://github.com/facebook/react/issues/3877 + return true; + } + + if (!hook.supportsFiber) { + { + 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" + ); + } // DevTools exists, even though it doesn't support Fiber. + + return true; + } + + try { + if (enableSchedulingProfiler) { + // Conditionally inject these hooks only if Timeline profiler is supported by this build. + // This gives DevTools a way to feature detect that isn't tied to version number + // (since profiling and timeline are controlled by different feature flags). + internals = assign({}, internals, { + getLaneLabelMap: getLaneLabelMap, + injectProfilingHooks: injectProfilingHooks + }); } - injectedHook.onCommitFiberRoot( - rendererID, - root, - schedulerPriority, - didError - ); + rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. + + injectedHook = hook; + } catch (err) { + // Catch all errors because it is unsafe to throw during initialization. + { + error("React instrumentation encountered an error: %s.", err); + } + } + + if (hook.checkDCE) { + // This is the real DevTools. + return true; + } else { + // This is likely a hook installed by Fast Refresh runtime. + return false; } - } catch (err) { + } + function onScheduleRoot(root, children) { { - if (!hasLoggedError) { - hasLoggedError = true; + if ( + injectedHook && + typeof injectedHook.onScheduleFiberRoot === "function" + ) { + try { + injectedHook.onScheduleFiberRoot(rendererID, root, children); + } catch (err) { + if (!hasLoggedError) { + hasLoggedError = true; - error("React instrumentation encountered an error: %s", err); + error("React instrumentation encountered an error: %s", err); + } + } } } } - } -} -function onPostCommitRoot(root) { - if ( - injectedHook && - typeof injectedHook.onPostCommitFiberRoot === "function" - ) { - try { - injectedHook.onPostCommitFiberRoot(rendererID, root); - } catch (err) { - { - if (!hasLoggedError) { - hasLoggedError = true; + function onCommitRoot(root, eventPriority) { + if ( + injectedHook && + typeof injectedHook.onCommitFiberRoot === "function" + ) { + try { + var didError = (root.current.flags & DidCapture) === DidCapture; + + if (enableProfilerTimer) { + var schedulerPriority; - error("React instrumentation encountered an error: %s", err); + switch (eventPriority) { + case DiscreteEventPriority: + schedulerPriority = ImmediatePriority; + break; + + case ContinuousEventPriority: + schedulerPriority = UserBlockingPriority; + break; + + case DefaultEventPriority: + schedulerPriority = NormalPriority$1; + break; + + case IdleEventPriority: + schedulerPriority = IdlePriority; + break; + + default: + schedulerPriority = NormalPriority$1; + break; + } + + injectedHook.onCommitFiberRoot( + rendererID, + root, + schedulerPriority, + didError + ); + } + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; + + error("React instrumentation encountered an error: %s", err); + } + } } } } - } -} -function onCommitUnmount(fiber) { - if (injectedHook && typeof injectedHook.onCommitFiberUnmount === "function") { - try { - injectedHook.onCommitFiberUnmount(rendererID, fiber); - } catch (err) { - { - if (!hasLoggedError) { - hasLoggedError = true; + function onPostCommitRoot(root) { + if ( + injectedHook && + typeof injectedHook.onPostCommitFiberRoot === "function" + ) { + try { + injectedHook.onPostCommitFiberRoot(rendererID, root); + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; - error("React instrumentation encountered an error: %s", err); + error("React instrumentation encountered an error: %s", err); + } + } } } } - } -} -function setIsStrictModeForDevtools(newIsStrictMode) { - { - if (typeof log$2 === "function") { - // We're in a test because Scheduler.log only exists - // in SchedulerMock. To reduce the noise in strict mode tests, - // suppress warnings and disable scheduler yielding during the double render - unstable_setDisableYieldValue(newIsStrictMode); - setSuppressWarning(newIsStrictMode); + function onCommitUnmount(fiber) { + if ( + injectedHook && + typeof injectedHook.onCommitFiberUnmount === "function" + ) { + try { + injectedHook.onCommitFiberUnmount(rendererID, fiber); + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; + + error("React instrumentation encountered an error: %s", err); + } + } + } + } } + function setIsStrictModeForDevtools(newIsStrictMode) { + { + if (typeof log$2 === "function") { + // We're in a test because Scheduler.log only exists + // in SchedulerMock. To reduce the noise in strict mode tests, + // suppress warnings and disable scheduler yielding during the double render + unstable_setDisableYieldValue(newIsStrictMode); + setSuppressWarning(newIsStrictMode); + } - if (injectedHook && typeof injectedHook.setStrictMode === "function") { - try { - injectedHook.setStrictMode(rendererID, newIsStrictMode); - } catch (err) { - { - if (!hasLoggedError) { - hasLoggedError = true; + if (injectedHook && typeof injectedHook.setStrictMode === "function") { + try { + injectedHook.setStrictMode(rendererID, newIsStrictMode); + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; - error("React instrumentation encountered an error: %s", err); + error("React instrumentation encountered an error: %s", err); + } + } } } } + } // Profiler API hooks + + function injectProfilingHooks(profilingHooks) { + injectedProfilingHooks = profilingHooks; } - } -} // Profiler API hooks -function injectProfilingHooks(profilingHooks) { - injectedProfilingHooks = profilingHooks; -} + function getLaneLabelMap() { + if (enableSchedulingProfiler) { + var map = new Map(); + var lane = 1; -function getLaneLabelMap() { - if (enableSchedulingProfiler) { - var map = new Map(); - var lane = 1; + for (var index = 0; index < TotalLanes; index++) { + var label = getLabelForLane(lane); + map.set(lane, label); + lane *= 2; + } - for (var index = 0; index < TotalLanes; index++) { - var label = getLabelForLane(lane); - map.set(lane, label); - lane *= 2; + return map; + } else { + return null; + } } - return map; - } else { - return null; - } -} - -function markCommitStarted(lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markCommitStarted === "function" - ) { - injectedProfilingHooks.markCommitStarted(lanes); + function markCommitStarted(lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markCommitStarted === "function" + ) { + injectedProfilingHooks.markCommitStarted(lanes); + } + } } - } -} -function markCommitStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markCommitStopped === "function" - ) { - injectedProfilingHooks.markCommitStopped(); + function markCommitStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markCommitStopped === "function" + ) { + injectedProfilingHooks.markCommitStopped(); + } + } } - } -} -function markComponentRenderStarted(fiber) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentRenderStarted === "function" - ) { - injectedProfilingHooks.markComponentRenderStarted(fiber); + function markComponentRenderStarted(fiber) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentRenderStarted === + "function" + ) { + injectedProfilingHooks.markComponentRenderStarted(fiber); + } + } } - } -} -function markComponentRenderStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentRenderStopped === "function" - ) { - injectedProfilingHooks.markComponentRenderStopped(); + function markComponentRenderStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentRenderStopped === + "function" + ) { + injectedProfilingHooks.markComponentRenderStopped(); + } + } } - } -} -function markComponentPassiveEffectMountStarted(fiber) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectMountStarted === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectMountStarted(fiber); + function markComponentPassiveEffectMountStarted(fiber) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectMountStarted === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectMountStarted(fiber); + } + } } - } -} -function markComponentPassiveEffectMountStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectMountStopped === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectMountStopped(); + function markComponentPassiveEffectMountStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectMountStopped === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectMountStopped(); + } + } } - } -} -function markComponentPassiveEffectUnmountStarted(fiber) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStarted === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectUnmountStarted(fiber); + function markComponentPassiveEffectUnmountStarted(fiber) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStarted === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectUnmountStarted( + fiber + ); + } + } } - } -} -function markComponentPassiveEffectUnmountStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStopped === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectUnmountStopped(); + function markComponentPassiveEffectUnmountStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStopped === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectUnmountStopped(); + } + } } - } -} -function markComponentLayoutEffectMountStarted(fiber) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectMountStarted === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectMountStarted(fiber); + function markComponentLayoutEffectMountStarted(fiber) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectMountStarted === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectMountStarted(fiber); + } + } } - } -} -function markComponentLayoutEffectMountStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectMountStopped === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectMountStopped(); + function markComponentLayoutEffectMountStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectMountStopped === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectMountStopped(); + } + } } - } -} -function markComponentLayoutEffectUnmountStarted(fiber) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber); + function markComponentLayoutEffectUnmountStarted(fiber) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber); + } + } } - } -} -function markComponentLayoutEffectUnmountStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectUnmountStopped(); + function markComponentLayoutEffectUnmountStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectUnmountStopped(); + } + } } - } -} -function markComponentErrored(fiber, thrownValue, lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentErrored === "function" - ) { - injectedProfilingHooks.markComponentErrored(fiber, thrownValue, lanes); + function markComponentErrored(fiber, thrownValue, lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentErrored === "function" + ) { + injectedProfilingHooks.markComponentErrored( + fiber, + thrownValue, + lanes + ); + } + } } - } -} -function markComponentSuspended(fiber, wakeable, lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentSuspended === "function" - ) { - injectedProfilingHooks.markComponentSuspended(fiber, wakeable, lanes); + function markComponentSuspended(fiber, wakeable, lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentSuspended === "function" + ) { + injectedProfilingHooks.markComponentSuspended(fiber, wakeable, lanes); + } + } } - } -} -function markLayoutEffectsStarted(lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markLayoutEffectsStarted === "function" - ) { - injectedProfilingHooks.markLayoutEffectsStarted(lanes); + function markLayoutEffectsStarted(lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markLayoutEffectsStarted === "function" + ) { + injectedProfilingHooks.markLayoutEffectsStarted(lanes); + } + } } - } -} -function markLayoutEffectsStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markLayoutEffectsStopped === "function" - ) { - injectedProfilingHooks.markLayoutEffectsStopped(); + function markLayoutEffectsStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markLayoutEffectsStopped === "function" + ) { + injectedProfilingHooks.markLayoutEffectsStopped(); + } + } } - } -} -function markPassiveEffectsStarted(lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markPassiveEffectsStarted === "function" - ) { - injectedProfilingHooks.markPassiveEffectsStarted(lanes); + function markPassiveEffectsStarted(lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markPassiveEffectsStarted === "function" + ) { + injectedProfilingHooks.markPassiveEffectsStarted(lanes); + } + } } - } -} -function markPassiveEffectsStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markPassiveEffectsStopped === "function" - ) { - injectedProfilingHooks.markPassiveEffectsStopped(); + function markPassiveEffectsStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markPassiveEffectsStopped === "function" + ) { + injectedProfilingHooks.markPassiveEffectsStopped(); + } + } } - } -} -function markRenderStarted(lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderStarted === "function" - ) { - injectedProfilingHooks.markRenderStarted(lanes); - } - } -} -function markRenderYielded() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderYielded === "function" - ) { - injectedProfilingHooks.markRenderYielded(); + function markRenderStarted(lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderStarted === "function" + ) { + injectedProfilingHooks.markRenderStarted(lanes); + } + } } - } -} -function markRenderStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderStopped === "function" - ) { - injectedProfilingHooks.markRenderStopped(); + function markRenderYielded() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderYielded === "function" + ) { + injectedProfilingHooks.markRenderYielded(); + } + } } - } -} -function markRenderScheduled(lane) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderScheduled === "function" - ) { - injectedProfilingHooks.markRenderScheduled(lane); + function markRenderStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderStopped === "function" + ) { + injectedProfilingHooks.markRenderStopped(); + } + } } - } -} -function markForceUpdateScheduled(fiber, lane) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markForceUpdateScheduled === "function" - ) { - injectedProfilingHooks.markForceUpdateScheduled(fiber, lane); + function markRenderScheduled(lane) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderScheduled === "function" + ) { + injectedProfilingHooks.markRenderScheduled(lane); + } + } } - } -} -function markStateUpdateScheduled(fiber, lane) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markStateUpdateScheduled === "function" - ) { - injectedProfilingHooks.markStateUpdateScheduled(fiber, lane); + function markForceUpdateScheduled(fiber, lane) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markForceUpdateScheduled === "function" + ) { + injectedProfilingHooks.markForceUpdateScheduled(fiber, lane); + } + } } - } -} + function markStateUpdateScheduled(fiber, lane) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markStateUpdateScheduled === "function" + ) { + injectedProfilingHooks.markStateUpdateScheduled(fiber, lane); + } + } + } + + var NoMode = + /* */ + 0; // TODO: Remove ConcurrentMode by reading from the root tag instead + + var ConcurrentMode = + /* */ + 1; + var ProfileMode = + /* */ + 2; + var DebugTracingMode = + /* */ + 4; + var StrictLegacyMode = + /* */ + 8; + var StrictEffectsMode = + /* */ + 16; + var ConcurrentUpdatesByDefaultMode = + /* */ + 32; + var NoStrictPassiveEffectsMode = + /* */ + 64; + + // TODO: This is pretty well supported by browsers. Maybe we can drop it. + var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; // Count leading zeros. + // Based on: + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 + + var log$1 = Math.log; + var LN2 = Math.LN2; + + function clz32Fallback(x) { + var asUint = x >>> 0; + + if (asUint === 0) { + return 32; + } + + return (31 - ((log$1(asUint) / LN2) | 0)) | 0; + } + + // If those values are changed that package should be rebuilt and redeployed. + + var TotalLanes = 31; + var NoLanes = + /* */ + 0; + var NoLane = + /* */ + 0; + var SyncHydrationLane = + /* */ + 1; + var SyncLane = + /* */ + 2; + var SyncLaneIndex = 1; + var InputContinuousHydrationLane = + /* */ + 4; + var InputContinuousLane = + /* */ + 8; + var DefaultHydrationLane = + /* */ + 16; + var DefaultLane = + /* */ + 32; + var SyncUpdateLanes = enableUnifiedSyncLane + ? SyncLane | InputContinuousLane | DefaultLane + : SyncLane; + var TransitionHydrationLane = + /* */ + 64; + var TransitionLanes = + /* */ + 4194176; + var TransitionLane1 = + /* */ + 128; + var TransitionLane2 = + /* */ + 256; + var TransitionLane3 = + /* */ + 512; + var TransitionLane4 = + /* */ + 1024; + var TransitionLane5 = + /* */ + 2048; + var TransitionLane6 = + /* */ + 4096; + var TransitionLane7 = + /* */ + 8192; + var TransitionLane8 = + /* */ + 16384; + var TransitionLane9 = + /* */ + 32768; + var TransitionLane10 = + /* */ + 65536; + var TransitionLane11 = + /* */ + 131072; + var TransitionLane12 = + /* */ + 262144; + var TransitionLane13 = + /* */ + 524288; + var TransitionLane14 = + /* */ + 1048576; + var TransitionLane15 = + /* */ + 2097152; + var RetryLanes = + /* */ + 62914560; + var RetryLane1 = + /* */ + 4194304; + var RetryLane2 = + /* */ + 8388608; + var RetryLane3 = + /* */ + 16777216; + var RetryLane4 = + /* */ + 33554432; + var SomeRetryLane = RetryLane1; + var SelectiveHydrationLane = + /* */ + 67108864; + var NonIdleLanes = + /* */ + 134217727; + var IdleHydrationLane = + /* */ + 134217728; + var IdleLane = + /* */ + 268435456; + var OffscreenLane = + /* */ + 536870912; + var DeferredLane = + /* */ + 1073741824; // Any lane that might schedule an update. This is used to detect infinite + // update loops, so it doesn't include hydration lanes or retries. + + var UpdateLanes = + SyncLane | InputContinuousLane | DefaultLane | TransitionLanes; // This function is used for the experimental timeline (react-devtools-timeline) + // It should be kept in sync with the Lanes values above. + + function getLabelForLane(lane) { + if (enableSchedulingProfiler) { + if (lane & SyncHydrationLane) { + return "SyncHydrationLane"; + } + + if (lane & SyncLane) { + return "Sync"; + } + + if (lane & InputContinuousHydrationLane) { + return "InputContinuousHydration"; + } + + if (lane & InputContinuousLane) { + return "InputContinuous"; + } + + if (lane & DefaultHydrationLane) { + return "DefaultHydration"; + } + + if (lane & DefaultLane) { + return "Default"; + } + + if (lane & TransitionHydrationLane) { + return "TransitionHydration"; + } + + if (lane & TransitionLanes) { + return "Transition"; + } -var NoMode = - /* */ - 0; // TODO: Remove ConcurrentMode by reading from the root tag instead - -var ConcurrentMode = - /* */ - 1; -var ProfileMode = - /* */ - 2; -var DebugTracingMode = - /* */ - 4; -var StrictLegacyMode = - /* */ - 8; -var StrictEffectsMode = - /* */ - 16; -var ConcurrentUpdatesByDefaultMode = - /* */ - 32; -var NoStrictPassiveEffectsMode = - /* */ - 64; - -// TODO: This is pretty well supported by browsers. Maybe we can drop it. -var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; // Count leading zeros. -// Based on: -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 - -var log$1 = Math.log; -var LN2 = Math.LN2; - -function clz32Fallback(x) { - var asUint = x >>> 0; - - if (asUint === 0) { - return 32; - } - - return (31 - ((log$1(asUint) / LN2) | 0)) | 0; -} + if (lane & RetryLanes) { + return "Retry"; + } -// If those values are changed that package should be rebuilt and redeployed. - -var TotalLanes = 31; -var NoLanes = - /* */ - 0; -var NoLane = - /* */ - 0; -var SyncHydrationLane = - /* */ - 1; -var SyncLane = - /* */ - 2; -var SyncLaneIndex = 1; -var InputContinuousHydrationLane = - /* */ - 4; -var InputContinuousLane = - /* */ - 8; -var DefaultHydrationLane = - /* */ - 16; -var DefaultLane = - /* */ - 32; -var SyncUpdateLanes = enableUnifiedSyncLane - ? SyncLane | InputContinuousLane | DefaultLane - : SyncLane; -var TransitionHydrationLane = - /* */ - 64; -var TransitionLanes = - /* */ - 4194176; -var TransitionLane1 = - /* */ - 128; -var TransitionLane2 = - /* */ - 256; -var TransitionLane3 = - /* */ - 512; -var TransitionLane4 = - /* */ - 1024; -var TransitionLane5 = - /* */ - 2048; -var TransitionLane6 = - /* */ - 4096; -var TransitionLane7 = - /* */ - 8192; -var TransitionLane8 = - /* */ - 16384; -var TransitionLane9 = - /* */ - 32768; -var TransitionLane10 = - /* */ - 65536; -var TransitionLane11 = - /* */ - 131072; -var TransitionLane12 = - /* */ - 262144; -var TransitionLane13 = - /* */ - 524288; -var TransitionLane14 = - /* */ - 1048576; -var TransitionLane15 = - /* */ - 2097152; -var RetryLanes = - /* */ - 62914560; -var RetryLane1 = - /* */ - 4194304; -var RetryLane2 = - /* */ - 8388608; -var RetryLane3 = - /* */ - 16777216; -var RetryLane4 = - /* */ - 33554432; -var SomeRetryLane = RetryLane1; -var SelectiveHydrationLane = - /* */ - 67108864; -var NonIdleLanes = - /* */ - 134217727; -var IdleHydrationLane = - /* */ - 134217728; -var IdleLane = - /* */ - 268435456; -var OffscreenLane = - /* */ - 536870912; -var DeferredLane = - /* */ - 1073741824; // Any lane that might schedule an update. This is used to detect infinite -// update loops, so it doesn't include hydration lanes or retries. - -var UpdateLanes = - SyncLane | InputContinuousLane | DefaultLane | TransitionLanes; // This function is used for the experimental timeline (react-devtools-timeline) -// It should be kept in sync with the Lanes values above. - -function getLabelForLane(lane) { - if (enableSchedulingProfiler) { - if (lane & SyncHydrationLane) { - return "SyncHydrationLane"; - } - - if (lane & SyncLane) { - return "Sync"; - } - - if (lane & InputContinuousHydrationLane) { - return "InputContinuousHydration"; - } - - if (lane & InputContinuousLane) { - return "InputContinuous"; - } - - if (lane & DefaultHydrationLane) { - return "DefaultHydration"; - } - - if (lane & DefaultLane) { - return "Default"; - } - - if (lane & TransitionHydrationLane) { - return "TransitionHydration"; - } - - if (lane & TransitionLanes) { - return "Transition"; - } - - if (lane & RetryLanes) { - return "Retry"; - } - - if (lane & SelectiveHydrationLane) { - return "SelectiveHydration"; - } + if (lane & SelectiveHydrationLane) { + return "SelectiveHydration"; + } - if (lane & IdleHydrationLane) { - return "IdleHydration"; - } + if (lane & IdleHydrationLane) { + return "IdleHydration"; + } - if (lane & IdleLane) { - return "Idle"; - } + if (lane & IdleLane) { + return "Idle"; + } - if (lane & OffscreenLane) { - return "Offscreen"; - } + if (lane & OffscreenLane) { + return "Offscreen"; + } - if (lane & DeferredLane) { - return "Deferred"; + if (lane & DeferredLane) { + return "Deferred"; + } + } } - } -} -var NoTimestamp = -1; -var nextTransitionLane = TransitionLane1; -var nextRetryLane = RetryLane1; - -function getHighestPriorityLanes(lanes) { - if (enableUnifiedSyncLane) { - var pendingSyncLanes = lanes & SyncUpdateLanes; - - if (pendingSyncLanes !== 0) { - return pendingSyncLanes; - } - } - - switch (getHighestPriorityLane(lanes)) { - case SyncHydrationLane: - return SyncHydrationLane; - - case SyncLane: - return SyncLane; - - case InputContinuousHydrationLane: - return InputContinuousHydrationLane; - - case InputContinuousLane: - return InputContinuousLane; - - case DefaultHydrationLane: - return DefaultHydrationLane; - - case DefaultLane: - return DefaultLane; - - case TransitionHydrationLane: - return TransitionHydrationLane; - - case TransitionLane1: - case TransitionLane2: - case TransitionLane3: - case TransitionLane4: - case TransitionLane5: - case TransitionLane6: - case TransitionLane7: - case TransitionLane8: - case TransitionLane9: - case TransitionLane10: - case TransitionLane11: - case TransitionLane12: - case TransitionLane13: - case TransitionLane14: - case TransitionLane15: - return lanes & TransitionLanes; - - case RetryLane1: - case RetryLane2: - case RetryLane3: - case RetryLane4: - return lanes & RetryLanes; - - case SelectiveHydrationLane: - return SelectiveHydrationLane; - - case IdleHydrationLane: - return IdleHydrationLane; - - case IdleLane: - return IdleLane; - - case OffscreenLane: - return OffscreenLane; - - case DeferredLane: - // This shouldn't be reachable because deferred work is always entangled - // with something else. - return NoLanes; + var NoTimestamp = -1; + var nextTransitionLane = TransitionLane1; + var nextRetryLane = RetryLane1; - default: - { - error("Should have found matching lanes. This is a bug in React."); - } // This shouldn't be reachable, but as a fallback, return the entire bitmask. + function getHighestPriorityLanes(lanes) { + if (enableUnifiedSyncLane) { + var pendingSyncLanes = lanes & SyncUpdateLanes; - return lanes; - } -} + if (pendingSyncLanes !== 0) { + return pendingSyncLanes; + } + } -function getNextLanes(root, wipLanes) { - // Early bailout if there's no pending work left. - var pendingLanes = root.pendingLanes; + switch (getHighestPriorityLane(lanes)) { + case SyncHydrationLane: + return SyncHydrationLane; - if (pendingLanes === NoLanes) { - return NoLanes; - } + case SyncLane: + return SyncLane; - var nextLanes = NoLanes; - var suspendedLanes = root.suspendedLanes; - var pingedLanes = root.pingedLanes; // Do not work on any idle work until all the non-idle work has finished, - // even if the work is suspended. + case InputContinuousHydrationLane: + return InputContinuousHydrationLane; - var nonIdlePendingLanes = pendingLanes & NonIdleLanes; + case InputContinuousLane: + return InputContinuousLane; - if (nonIdlePendingLanes !== NoLanes) { - var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; + case DefaultHydrationLane: + return DefaultHydrationLane; - if (nonIdleUnblockedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); - } else { - var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; + case DefaultLane: + return DefaultLane; - if (nonIdlePingedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); - } - } - } else { - // The only remaining work is Idle. - var unblockedLanes = pendingLanes & ~suspendedLanes; + case TransitionHydrationLane: + return TransitionHydrationLane; - if (unblockedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(unblockedLanes); - } else { - if (pingedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(pingedLanes); - } - } - } + case TransitionLane1: + case TransitionLane2: + case TransitionLane3: + case TransitionLane4: + case TransitionLane5: + case TransitionLane6: + case TransitionLane7: + case TransitionLane8: + case TransitionLane9: + case TransitionLane10: + case TransitionLane11: + case TransitionLane12: + case TransitionLane13: + case TransitionLane14: + case TransitionLane15: + return lanes & TransitionLanes; - if (nextLanes === NoLanes) { - // This should only be reachable if we're suspended - // TODO: Consider warning in this path if a fallback timer is not scheduled. - return NoLanes; - } // If we're already in the middle of a render, switching lanes will interrupt - // it and we'll lose our progress. We should only do this if the new lanes are - // higher priority. + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + return lanes & RetryLanes; - if ( - wipLanes !== NoLanes && - wipLanes !== nextLanes && // If we already suspended with a delay, then interrupting is fine. Don't - // bother waiting until the root is complete. - (wipLanes & suspendedLanes) === NoLanes - ) { - var nextLane = getHighestPriorityLane(nextLanes); - var wipLane = getHighestPriorityLane(wipLanes); + case SelectiveHydrationLane: + return SelectiveHydrationLane; - if ( - // Tests whether the next lane is equal or lower priority than the wip - // one. This works because the bits decrease in priority as you go left. - nextLane >= wipLane || // Default priority updates should not interrupt transition updates. The - // only difference between default updates and transition updates is that - // default updates do not support refresh transitions. - (nextLane === DefaultLane && (wipLane & TransitionLanes) !== NoLanes) - ) { - // Keep working on the existing in-progress tree. Do not interrupt. - return wipLanes; - } - } + case IdleHydrationLane: + return IdleHydrationLane; - return nextLanes; -} -function getEntangledLanes(root, renderLanes) { - var entangledLanes = renderLanes; - - if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode); - else if ((entangledLanes & InputContinuousLane) !== NoLanes) { - // When updates are sync by default, we entangle continuous priority updates - // and default updates, so they render in the same batch. The only reason - // they use separate lanes is because continuous updates should interrupt - // transitions, but default updates should not. - entangledLanes |= entangledLanes & DefaultLane; - } // Check for entangled lanes and add them to the batch. - // - // A lane is said to be entangled with another when it's not allowed to render - // in a batch that does not also include the other lane. Typically we do this - // when multiple updates have the same source, and we only want to respond to - // the most recent event from that source. - // - // Note that we apply entanglements *after* checking for partial work above. - // This means that if a lane is entangled during an interleaved event while - // it's already rendering, we won't interrupt it. This is intentional, since - // entanglement is usually "best effort": we'll try our best to render the - // lanes in the same batch, but it's not worth throwing out partially - // completed work in order to do it. - // TODO: Reconsider this. The counter-argument is that the partial work - // represents an intermediate state, which we don't want to show to the user. - // And by spending extra time finishing it, we're increasing the amount of - // time it takes to show the final state, which is what they are actually - // waiting for. - // - // For those exceptions where entanglement is semantically important, - // we should ensure that there is no partial work at the - // time we apply the entanglement. - - var allEntangledLanes = root.entangledLanes; - - if (allEntangledLanes !== NoLanes) { - var entanglements = root.entanglements; - var lanes = entangledLanes & allEntangledLanes; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - entangledLanes |= entanglements[index]; - lanes &= ~lane; - } - } - - return entangledLanes; -} + case IdleLane: + return IdleLane; -function computeExpirationTime(lane, currentTime) { - switch (lane) { - case SyncHydrationLane: - case SyncLane: - case InputContinuousHydrationLane: - case InputContinuousLane: - // User interactions should expire slightly more quickly. - // - // NOTE: This is set to the corresponding constant as in Scheduler.js. - // When we made it larger, a product metric in www regressed, suggesting - // there's a user interaction that's being starved by a series of - // synchronous updates. If that theory is correct, the proper solution is - // to fix the starvation. However, this scenario supports the idea that - // expiration times are an important safeguard when starvation - // does happen. - return currentTime + 250; - - case DefaultHydrationLane: - case DefaultLane: - case TransitionHydrationLane: - case TransitionLane1: - case TransitionLane2: - case TransitionLane3: - case TransitionLane4: - case TransitionLane5: - case TransitionLane6: - case TransitionLane7: - case TransitionLane8: - case TransitionLane9: - case TransitionLane10: - case TransitionLane11: - case TransitionLane12: - case TransitionLane13: - case TransitionLane14: - case TransitionLane15: - return currentTime + 5000; - - case RetryLane1: - case RetryLane2: - case RetryLane3: - case RetryLane4: - // TODO: Retries should be allowed to expire if they are CPU bound for - // too long, but when I made this change it caused a spike in browser - // crashes. There must be some other underlying bug; not super urgent but - // ideally should figure out why and fix it. Unfortunately we don't have - // a repro for the crashes, only detected via production metrics. - return NoTimestamp; - - case SelectiveHydrationLane: - case IdleHydrationLane: - case IdleLane: - case OffscreenLane: - case DeferredLane: - // Anything idle priority or lower should never expire. - return NoTimestamp; - - default: - { - error("Should have found matching lanes. This is a bug in React."); - } + case OffscreenLane: + return OffscreenLane; - return NoTimestamp; - } -} + case DeferredLane: + // This shouldn't be reachable because deferred work is always entangled + // with something else. + return NoLanes; -function markStarvedLanesAsExpired(root, currentTime) { - // TODO: This gets called every time we yield. We can optimize by storing - // the earliest expiration time on the root. Then use that to quickly bail out - // of this function. - var pendingLanes = root.pendingLanes; - var suspendedLanes = root.suspendedLanes; - var pingedLanes = root.pingedLanes; - var expirationTimes = root.expirationTimes; // Iterate through the pending lanes and check if we've reached their - // expiration time. If so, we'll assume the update is being starved and mark - // it as expired to force it to finish. - // TODO: We should be able to replace this with upgradePendingLanesToSync - // - // We exclude retry lanes because those must always be time sliced, in order - // to unwrap uncached promises. - // TODO: Write a test for this - - var lanes = pendingLanes & ~RetryLanes; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - var expirationTime = expirationTimes[index]; - - if (expirationTime === NoTimestamp) { - // Found a pending lane with no expiration time. If it's not suspended, or - // if it's pinged, assume it's CPU-bound. Compute a new expiration time - // using the current time. - if ( - (lane & suspendedLanes) === NoLanes || - (lane & pingedLanes) !== NoLanes - ) { - // Assumes timestamps are monotonically increasing. - expirationTimes[index] = computeExpirationTime(lane, currentTime); + default: + { + error("Should have found matching lanes. This is a bug in React."); + } // This shouldn't be reachable, but as a fallback, return the entire bitmask. + + return lanes; } - } else if (expirationTime <= currentTime) { - // This lane expired - root.expiredLanes |= lane; } - lanes &= ~lane; - } -} // This returns the highest priority pending lanes regardless of whether they -function getLanesToRetrySynchronouslyOnError(root, originallyAttemptedLanes) { - if (root.errorRecoveryDisabledLanes & originallyAttemptedLanes) { - // The error recovery mechanism is disabled until these lanes are cleared. - return NoLanes; - } + function getNextLanes(root, wipLanes) { + // Early bailout if there's no pending work left. + var pendingLanes = root.pendingLanes; - var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; + if (pendingLanes === NoLanes) { + return NoLanes; + } - if (everythingButOffscreen !== NoLanes) { - return everythingButOffscreen; - } + var nextLanes = NoLanes; + var suspendedLanes = root.suspendedLanes; + var pingedLanes = root.pingedLanes; // Do not work on any idle work until all the non-idle work has finished, + // even if the work is suspended. - if (everythingButOffscreen & OffscreenLane) { - return OffscreenLane; - } + var nonIdlePendingLanes = pendingLanes & NonIdleLanes; - return NoLanes; -} -function includesSyncLane(lanes) { - return (lanes & (SyncLane | SyncHydrationLane)) !== NoLanes; -} -function includesNonIdleWork(lanes) { - return (lanes & NonIdleLanes) !== NoLanes; -} -function includesOnlyRetries(lanes) { - return (lanes & RetryLanes) === lanes; -} -function includesOnlyNonUrgentLanes(lanes) { - // TODO: Should hydration lanes be included here? This function is only - // used in `updateDeferredValueImpl`. - var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; - return (lanes & UrgentLanes) === NoLanes; -} -function includesOnlyTransitions(lanes) { - return (lanes & TransitionLanes) === lanes; -} -function includesBlockingLane(root, lanes) { - if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode) { - // Concurrent updates by default always use time slicing. - return false; - } - - var SyncDefaultLanes = - InputContinuousHydrationLane | - InputContinuousLane | - DefaultHydrationLane | - DefaultLane; - return (lanes & SyncDefaultLanes) !== NoLanes; -} -function includesExpiredLane(root, lanes) { - // This is a separate check from includesBlockingLane because a lane can - // expire after a render has already started. - return (lanes & root.expiredLanes) !== NoLanes; -} -function isTransitionLane(lane) { - return (lane & TransitionLanes) !== NoLanes; -} -function claimNextTransitionLane() { - // Cycle through the lanes, assigning each new transition to the next lane. - // In most cases, this means every transition gets its own lane, until we - // run out of lanes and cycle back to the beginning. - var lane = nextTransitionLane; - nextTransitionLane <<= 1; - - if ((nextTransitionLane & TransitionLanes) === NoLanes) { - nextTransitionLane = TransitionLane1; - } - - return lane; -} -function claimNextRetryLane() { - var lane = nextRetryLane; - nextRetryLane <<= 1; + if (nonIdlePendingLanes !== NoLanes) { + var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; - if ((nextRetryLane & RetryLanes) === NoLanes) { - nextRetryLane = RetryLane1; - } + if (nonIdleUnblockedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); + } else { + var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; - return lane; -} -function getHighestPriorityLane(lanes) { - return lanes & -lanes; -} -function pickArbitraryLane(lanes) { - // This wrapper function gets inlined. Only exists so to communicate that it - // doesn't matter which bit is selected; you can pick any bit without - // affecting the algorithms where its used. Here I'm using - // getHighestPriorityLane because it requires the fewest operations. - return getHighestPriorityLane(lanes); -} + if (nonIdlePingedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); + } + } + } else { + // The only remaining work is Idle. + var unblockedLanes = pendingLanes & ~suspendedLanes; -function pickArbitraryLaneIndex(lanes) { - return 31 - clz32(lanes); -} + if (unblockedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(unblockedLanes); + } else { + if (pingedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(pingedLanes); + } + } + } -function laneToIndex(lane) { - return pickArbitraryLaneIndex(lane); -} + if (nextLanes === NoLanes) { + // This should only be reachable if we're suspended + // TODO: Consider warning in this path if a fallback timer is not scheduled. + return NoLanes; + } // If we're already in the middle of a render, switching lanes will interrupt + // it and we'll lose our progress. We should only do this if the new lanes are + // higher priority. -function includesSomeLane(a, b) { - return (a & b) !== NoLanes; -} -function isSubsetOfLanes(set, subset) { - return (set & subset) === subset; -} -function mergeLanes(a, b) { - return a | b; -} -function removeLanes(set, subset) { - return set & ~subset; -} -function intersectLanes(a, b) { - return a & b; -} // Seems redundant, but it changes the type from a single lane (used for -// updates) to a group of lanes (used for flushing work). + if ( + wipLanes !== NoLanes && + wipLanes !== nextLanes && // If we already suspended with a delay, then interrupting is fine. Don't + // bother waiting until the root is complete. + (wipLanes & suspendedLanes) === NoLanes + ) { + var nextLane = getHighestPriorityLane(nextLanes); + var wipLane = getHighestPriorityLane(wipLanes); -function laneToLanes(lane) { - return lane; -} -function createLaneMap(initial) { - // Intentionally pushing one by one. - // https://v8.dev/blog/elements-kinds#avoid-creating-holes - var laneMap = []; + if ( + // Tests whether the next lane is equal or lower priority than the wip + // one. This works because the bits decrease in priority as you go left. + nextLane >= wipLane || // Default priority updates should not interrupt transition updates. The + // only difference between default updates and transition updates is that + // default updates do not support refresh transitions. + (nextLane === DefaultLane && (wipLane & TransitionLanes) !== NoLanes) + ) { + // Keep working on the existing in-progress tree. Do not interrupt. + return wipLanes; + } + } - for (var i = 0; i < TotalLanes; i++) { - laneMap.push(initial); - } + return nextLanes; + } + function getEntangledLanes(root, renderLanes) { + var entangledLanes = renderLanes; - return laneMap; -} -function markRootUpdated(root, updateLane) { - root.pendingLanes |= updateLane; // If there are any suspended transitions, it's possible this new update - // could unblock them. Clear the suspended lanes so that we can try rendering - // them again. - // - // TODO: We really only need to unsuspend only lanes that are in the - // `subtreeLanes` of the updated fiber, or the update lanes of the return - // path. This would exclude suspended updates in an unrelated sibling tree, - // since there's no way for this update to unblock it. - // - // We don't do this if the incoming update is idle, because we never process - // idle updates until after all the regular updates have finished; there's no - // way it could unblock a transition. - - if (updateLane !== IdleLane) { - root.suspendedLanes = NoLanes; - root.pingedLanes = NoLanes; - } -} -function markRootSuspended$1(root, suspendedLanes, spawnedLane) { - root.suspendedLanes |= suspendedLanes; - root.pingedLanes &= ~suspendedLanes; // The suspended lanes are no longer CPU-bound. Clear their expiration times. - - var expirationTimes = root.expirationTimes; - var lanes = suspendedLanes; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - expirationTimes[index] = NoTimestamp; - lanes &= ~lane; - } - - if (spawnedLane !== NoLane) { - markSpawnedDeferredLane(root, spawnedLane, suspendedLanes); - } -} -function markRootPinged(root, pingedLanes) { - root.pingedLanes |= root.suspendedLanes & pingedLanes; -} -function markRootFinished(root, remainingLanes, spawnedLane) { - var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; - root.pendingLanes = remainingLanes; // Let's try everything again + if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode); + else if ((entangledLanes & InputContinuousLane) !== NoLanes) { + // When updates are sync by default, we entangle continuous priority updates + // and default updates, so they render in the same batch. The only reason + // they use separate lanes is because continuous updates should interrupt + // transitions, but default updates should not. + entangledLanes |= entangledLanes & DefaultLane; + } // Check for entangled lanes and add them to the batch. + // + // A lane is said to be entangled with another when it's not allowed to render + // in a batch that does not also include the other lane. Typically we do this + // when multiple updates have the same source, and we only want to respond to + // the most recent event from that source. + // + // Note that we apply entanglements *after* checking for partial work above. + // This means that if a lane is entangled during an interleaved event while + // it's already rendering, we won't interrupt it. This is intentional, since + // entanglement is usually "best effort": we'll try our best to render the + // lanes in the same batch, but it's not worth throwing out partially + // completed work in order to do it. + // TODO: Reconsider this. The counter-argument is that the partial work + // represents an intermediate state, which we don't want to show to the user. + // And by spending extra time finishing it, we're increasing the amount of + // time it takes to show the final state, which is what they are actually + // waiting for. + // + // For those exceptions where entanglement is semantically important, + // we should ensure that there is no partial work at the + // time we apply the entanglement. - root.suspendedLanes = NoLanes; - root.pingedLanes = NoLanes; - root.expiredLanes &= remainingLanes; - root.entangledLanes &= remainingLanes; - root.errorRecoveryDisabledLanes &= remainingLanes; - root.shellSuspendCounter = 0; - var entanglements = root.entanglements; - var expirationTimes = root.expirationTimes; - var hiddenUpdates = root.hiddenUpdates; // Clear the lanes that no longer have pending work + var allEntangledLanes = root.entangledLanes; - var lanes = noLongerPendingLanes; + if (allEntangledLanes !== NoLanes) { + var entanglements = root.entanglements; + var lanes = entangledLanes & allEntangledLanes; - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - entanglements[index] = NoLanes; - expirationTimes[index] = NoTimestamp; - var hiddenUpdatesForLane = hiddenUpdates[index]; + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + entangledLanes |= entanglements[index]; + lanes &= ~lane; + } + } - if (hiddenUpdatesForLane !== null) { - hiddenUpdates[index] = null; // "Hidden" updates are updates that were made to a hidden component. They - // have special logic associated with them because they may be entangled - // with updates that occur outside that tree. But once the outer tree - // commits, they behave like regular updates. + return entangledLanes; + } - for (var i = 0; i < hiddenUpdatesForLane.length; i++) { - var update = hiddenUpdatesForLane[i]; + function computeExpirationTime(lane, currentTime) { + switch (lane) { + case SyncHydrationLane: + case SyncLane: + case InputContinuousHydrationLane: + case InputContinuousLane: + // User interactions should expire slightly more quickly. + // + // NOTE: This is set to the corresponding constant as in Scheduler.js. + // When we made it larger, a product metric in www regressed, suggesting + // there's a user interaction that's being starved by a series of + // synchronous updates. If that theory is correct, the proper solution is + // to fix the starvation. However, this scenario supports the idea that + // expiration times are an important safeguard when starvation + // does happen. + return currentTime + 250; + + case DefaultHydrationLane: + case DefaultLane: + case TransitionHydrationLane: + case TransitionLane1: + case TransitionLane2: + case TransitionLane3: + case TransitionLane4: + case TransitionLane5: + case TransitionLane6: + case TransitionLane7: + case TransitionLane8: + case TransitionLane9: + case TransitionLane10: + case TransitionLane11: + case TransitionLane12: + case TransitionLane13: + case TransitionLane14: + case TransitionLane15: + return currentTime + 5000; + + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + // TODO: Retries should be allowed to expire if they are CPU bound for + // too long, but when I made this change it caused a spike in browser + // crashes. There must be some other underlying bug; not super urgent but + // ideally should figure out why and fix it. Unfortunately we don't have + // a repro for the crashes, only detected via production metrics. + return NoTimestamp; + + case SelectiveHydrationLane: + case IdleHydrationLane: + case IdleLane: + case OffscreenLane: + case DeferredLane: + // Anything idle priority or lower should never expire. + return NoTimestamp; + + default: + { + error("Should have found matching lanes. This is a bug in React."); + } - if (update !== null) { - update.lane &= ~OffscreenLane; - } + return NoTimestamp; } } - lanes &= ~lane; - } + function markStarvedLanesAsExpired(root, currentTime) { + // TODO: This gets called every time we yield. We can optimize by storing + // the earliest expiration time on the root. Then use that to quickly bail out + // of this function. + var pendingLanes = root.pendingLanes; + var suspendedLanes = root.suspendedLanes; + var pingedLanes = root.pingedLanes; + var expirationTimes = root.expirationTimes; // Iterate through the pending lanes and check if we've reached their + // expiration time. If so, we'll assume the update is being starved and mark + // it as expired to force it to finish. + // TODO: We should be able to replace this with upgradePendingLanesToSync + // + // We exclude retry lanes because those must always be time sliced, in order + // to unwrap uncached promises. + // TODO: Write a test for this - if (spawnedLane !== NoLane) { - markSpawnedDeferredLane( - root, - spawnedLane, // This render finished successfully without suspending, so we don't need - // to entangle the spawned task with the parent task. - NoLanes - ); - } -} + var lanes = pendingLanes & ~RetryLanes; -function markSpawnedDeferredLane(root, spawnedLane, entangledLanes) { - // This render spawned a deferred task. Mark it as pending. - root.pendingLanes |= spawnedLane; - root.suspendedLanes &= ~spawnedLane; // Entangle the spawned lane with the DeferredLane bit so that we know it - // was the result of another render. This lets us avoid a useDeferredValue - // waterfall — only the first level will defer. - - var spawnedLaneIndex = laneToIndex(spawnedLane); - root.entangledLanes |= spawnedLane; - root.entanglements[spawnedLaneIndex] |= - DeferredLane | // If the parent render task suspended, we must also entangle those lanes - // with the spawned task, so that the deferred task includes all the same - // updates that the parent task did. We can exclude any lane that is not - // used for updates (e.g. Offscreen). - (entangledLanes & UpdateLanes); -} + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + var expirationTime = expirationTimes[index]; -function markRootEntangled(root, entangledLanes) { - // In addition to entangling each of the given lanes with each other, we also - // have to consider _transitive_ entanglements. For each lane that is already - // entangled with *any* of the given lanes, that lane is now transitively - // entangled with *all* the given lanes. - // - // Translated: If C is entangled with A, then entangling A with B also - // entangles C with B. - // - // If this is hard to grasp, it might help to intentionally break this - // function and look at the tests that fail in ReactTransition-test.js. Try - // commenting out one of the conditions below. - var rootEntangledLanes = (root.entangledLanes |= entangledLanes); - var entanglements = root.entanglements; - var lanes = rootEntangledLanes; - - while (lanes) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; + if (expirationTime === NoTimestamp) { + // Found a pending lane with no expiration time. If it's not suspended, or + // if it's pinged, assume it's CPU-bound. Compute a new expiration time + // using the current time. + if ( + (lane & suspendedLanes) === NoLanes || + (lane & pingedLanes) !== NoLanes + ) { + // Assumes timestamps are monotonically increasing. + expirationTimes[index] = computeExpirationTime(lane, currentTime); + } + } else if (expirationTime <= currentTime) { + // This lane expired + root.expiredLanes |= lane; + } - if ( - // Is this one of the newly entangled lanes? - (lane & entangledLanes) | // Is this lane transitively entangled with the newly entangled lanes? - (entanglements[index] & entangledLanes) + lanes &= ~lane; + } + } // This returns the highest priority pending lanes regardless of whether they + function getLanesToRetrySynchronouslyOnError( + root, + originallyAttemptedLanes ) { - entanglements[index] |= entangledLanes; - } + if (root.errorRecoveryDisabledLanes & originallyAttemptedLanes) { + // The error recovery mechanism is disabled until these lanes are cleared. + return NoLanes; + } - lanes &= ~lane; - } -} -function upgradePendingLaneToSync(root, lane) { - // Since we're upgrading the priority of the given lane, there is now pending - // sync work. - root.pendingLanes |= SyncLane; // Entangle the sync lane with the lane we're upgrading. This means SyncLane - // will not be allowed to finish without also finishing the given lane. - - root.entangledLanes |= SyncLane; - root.entanglements[SyncLaneIndex] |= lane; -} -function markHiddenUpdate(root, update, lane) { - var index = laneToIndex(lane); - var hiddenUpdates = root.hiddenUpdates; - var hiddenUpdatesForLane = hiddenUpdates[index]; - - if (hiddenUpdatesForLane === null) { - hiddenUpdates[index] = [update]; - } else { - hiddenUpdatesForLane.push(update); - } - - update.lane = lane | OffscreenLane; -} -function getBumpedLaneForHydration(root, renderLanes) { - var renderLane = getHighestPriorityLane(renderLanes); - var lane; - - if (enableUnifiedSyncLane && (renderLane & SyncUpdateLanes) !== NoLane) { - lane = SyncHydrationLane; - } else { - switch (renderLane) { - case SyncLane: - lane = SyncHydrationLane; - break; - - case InputContinuousLane: - lane = InputContinuousHydrationLane; - break; - - case DefaultLane: - lane = DefaultHydrationLane; - break; - - case TransitionLane1: - case TransitionLane2: - case TransitionLane3: - case TransitionLane4: - case TransitionLane5: - case TransitionLane6: - case TransitionLane7: - case TransitionLane8: - case TransitionLane9: - case TransitionLane10: - case TransitionLane11: - case TransitionLane12: - case TransitionLane13: - case TransitionLane14: - case TransitionLane15: - case RetryLane1: - case RetryLane2: - case RetryLane3: - case RetryLane4: - lane = TransitionHydrationLane; - break; - - case IdleLane: - lane = IdleHydrationLane; - break; - - default: - // Everything else is already either a hydration lane, or shouldn't - // be retried at a hydration lane. - lane = NoLane; - break; - } - } // Check if the lane we chose is suspended. If so, that indicates that we - // already attempted and failed to hydrate at that level. Also check if we're - // already rendering that lane, which is rare but could happen. - - if ((lane & (root.suspendedLanes | renderLanes)) !== NoLane) { - // Give up trying to hydrate and fall back to client render. - return NoLane; - } - - return lane; -} -function addFiberToLanesMap(root, fiber, lanes) { - if (!isDevToolsPresent) { - return; - } - - var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; - - while (lanes > 0) { - var index = laneToIndex(lanes); - var lane = 1 << index; - var updaters = pendingUpdatersLaneMap[index]; - updaters.add(fiber); - lanes &= ~lane; - } -} -function movePendingFibersToMemoized(root, lanes) { - if (!isDevToolsPresent) { - return; - } + var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; - var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; - var memoizedUpdaters = root.memoizedUpdaters; + if (everythingButOffscreen !== NoLanes) { + return everythingButOffscreen; + } - while (lanes > 0) { - var index = laneToIndex(lanes); - var lane = 1 << index; - var updaters = pendingUpdatersLaneMap[index]; + if (everythingButOffscreen & OffscreenLane) { + return OffscreenLane; + } - if (updaters.size > 0) { - updaters.forEach(function (fiber) { - var alternate = fiber.alternate; + return NoLanes; + } + function includesSyncLane(lanes) { + return (lanes & (SyncLane | SyncHydrationLane)) !== NoLanes; + } + function includesNonIdleWork(lanes) { + return (lanes & NonIdleLanes) !== NoLanes; + } + function includesOnlyRetries(lanes) { + return (lanes & RetryLanes) === lanes; + } + function includesOnlyNonUrgentLanes(lanes) { + // TODO: Should hydration lanes be included here? This function is only + // used in `updateDeferredValueImpl`. + var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; + return (lanes & UrgentLanes) === NoLanes; + } + function includesOnlyTransitions(lanes) { + return (lanes & TransitionLanes) === lanes; + } + function includesBlockingLane(root, lanes) { + if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode) { + // Concurrent updates by default always use time slicing. + return false; + } - if (alternate === null || !memoizedUpdaters.has(alternate)) { - memoizedUpdaters.add(fiber); - } - }); - updaters.clear(); + var SyncDefaultLanes = + InputContinuousHydrationLane | + InputContinuousLane | + DefaultHydrationLane | + DefaultLane; + return (lanes & SyncDefaultLanes) !== NoLanes; + } + function includesExpiredLane(root, lanes) { + // This is a separate check from includesBlockingLane because a lane can + // expire after a render has already started. + return (lanes & root.expiredLanes) !== NoLanes; + } + function isTransitionLane(lane) { + return (lane & TransitionLanes) !== NoLanes; } + function claimNextTransitionLane() { + // Cycle through the lanes, assigning each new transition to the next lane. + // In most cases, this means every transition gets its own lane, until we + // run out of lanes and cycle back to the beginning. + var lane = nextTransitionLane; + nextTransitionLane <<= 1; - lanes &= ~lane; - } -} -function addTransitionToLanesMap(root, transition, lane) { - if (enableTransitionTracing) { - var transitionLanesMap = root.transitionLanes; - var index = laneToIndex(lane); - var transitions = transitionLanesMap[index]; + if ((nextTransitionLane & TransitionLanes) === NoLanes) { + nextTransitionLane = TransitionLane1; + } - if (transitions === null) { - transitions = new Set(); + return lane; } + function claimNextRetryLane() { + var lane = nextRetryLane; + nextRetryLane <<= 1; - transitions.add(transition); - transitionLanesMap[index] = transitions; - } -} -function getTransitionsForLanes(root, lanes) { - if (!enableTransitionTracing) { - return null; - } + if ((nextRetryLane & RetryLanes) === NoLanes) { + nextRetryLane = RetryLane1; + } - var transitionsForLanes = []; + return lane; + } + function getHighestPriorityLane(lanes) { + return lanes & -lanes; + } + function pickArbitraryLane(lanes) { + // This wrapper function gets inlined. Only exists so to communicate that it + // doesn't matter which bit is selected; you can pick any bit without + // affecting the algorithms where its used. Here I'm using + // getHighestPriorityLane because it requires the fewest operations. + return getHighestPriorityLane(lanes); + } - while (lanes > 0) { - var index = laneToIndex(lanes); - var lane = 1 << index; - var transitions = root.transitionLanes[index]; + function pickArbitraryLaneIndex(lanes) { + return 31 - clz32(lanes); + } - if (transitions !== null) { - transitions.forEach(function (transition) { - transitionsForLanes.push(transition); - }); + function laneToIndex(lane) { + return pickArbitraryLaneIndex(lane); } - lanes &= ~lane; - } + function includesSomeLane(a, b) { + return (a & b) !== NoLanes; + } + function isSubsetOfLanes(set, subset) { + return (set & subset) === subset; + } + function mergeLanes(a, b) { + return a | b; + } + function removeLanes(set, subset) { + return set & ~subset; + } + function intersectLanes(a, b) { + return a & b; + } // Seems redundant, but it changes the type from a single lane (used for + // updates) to a group of lanes (used for flushing work). - if (transitionsForLanes.length === 0) { - return null; - } + function laneToLanes(lane) { + return lane; + } + function createLaneMap(initial) { + // Intentionally pushing one by one. + // https://v8.dev/blog/elements-kinds#avoid-creating-holes + var laneMap = []; - return transitionsForLanes; -} -function clearTransitionsForLanes(root, lanes) { - if (!enableTransitionTracing) { - return; - } + for (var i = 0; i < TotalLanes; i++) { + laneMap.push(initial); + } - while (lanes > 0) { - var index = laneToIndex(lanes); - var lane = 1 << index; - var transitions = root.transitionLanes[index]; + return laneMap; + } + function markRootUpdated(root, updateLane) { + root.pendingLanes |= updateLane; // If there are any suspended transitions, it's possible this new update + // could unblock them. Clear the suspended lanes so that we can try rendering + // them again. + // + // TODO: We really only need to unsuspend only lanes that are in the + // `subtreeLanes` of the updated fiber, or the update lanes of the return + // path. This would exclude suspended updates in an unrelated sibling tree, + // since there's no way for this update to unblock it. + // + // We don't do this if the incoming update is idle, because we never process + // idle updates until after all the regular updates have finished; there's no + // way it could unblock a transition. - if (transitions !== null) { - root.transitionLanes[index] = null; + if (updateLane !== IdleLane) { + root.suspendedLanes = NoLanes; + root.pingedLanes = NoLanes; + } } + function markRootSuspended$1(root, suspendedLanes, spawnedLane) { + root.suspendedLanes |= suspendedLanes; + root.pingedLanes &= ~suspendedLanes; // The suspended lanes are no longer CPU-bound. Clear their expiration times. - lanes &= ~lane; - } -} + var expirationTimes = root.expirationTimes; + var lanes = suspendedLanes; -var DiscreteEventPriority = SyncLane; -var ContinuousEventPriority = InputContinuousLane; -var DefaultEventPriority = DefaultLane; -var IdleEventPriority = IdleLane; -var currentUpdatePriority = NoLane; -function getCurrentUpdatePriority() { - return currentUpdatePriority; -} -function setCurrentUpdatePriority(newPriority) { - currentUpdatePriority = newPriority; -} -function higherEventPriority(a, b) { - return a !== 0 && a < b ? a : b; -} -function lowerEventPriority(a, b) { - return a === 0 || a > b ? a : b; -} -function isHigherEventPriority(a, b) { - return a !== 0 && a < b; -} -function lanesToEventPriority(lanes) { - var lane = getHighestPriorityLane(lanes); + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + expirationTimes[index] = NoTimestamp; + lanes &= ~lane; + } - if (!isHigherEventPriority(DiscreteEventPriority, lane)) { - return DiscreteEventPriority; - } + if (spawnedLane !== NoLane) { + markSpawnedDeferredLane(root, spawnedLane, suspendedLanes); + } + } + function markRootPinged(root, pingedLanes) { + root.pingedLanes |= root.suspendedLanes & pingedLanes; + } + function markRootFinished(root, remainingLanes, spawnedLane) { + var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; + root.pendingLanes = remainingLanes; // Let's try everything again - if (!isHigherEventPriority(ContinuousEventPriority, lane)) { - return ContinuousEventPriority; - } + root.suspendedLanes = NoLanes; + root.pingedLanes = NoLanes; + root.expiredLanes &= remainingLanes; + root.entangledLanes &= remainingLanes; + root.errorRecoveryDisabledLanes &= remainingLanes; + root.shellSuspendCounter = 0; + var entanglements = root.entanglements; + var expirationTimes = root.expirationTimes; + var hiddenUpdates = root.hiddenUpdates; // Clear the lanes that no longer have pending work - if (includesNonIdleWork(lane)) { - return DefaultEventPriority; - } + var lanes = noLongerPendingLanes; - return IdleEventPriority; -} + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + entanglements[index] = NoLanes; + expirationTimes[index] = NoTimestamp; + var hiddenUpdatesForLane = hiddenUpdates[index]; -// Renderers that don't support hydration -// can re-export everything from this module. -function shim$2() { - throw new Error( - "The current renderer does not support hydration. " + - "This error is likely caused by a bug in React. " + - "Please file an issue." - ); -} // Hydration (when unsupported) -var isSuspenseInstancePending = shim$2; -var isSuspenseInstanceFallback = shim$2; -var getSuspenseInstanceFallbackErrorDetails = shim$2; -var registerSuspenseInstanceRetry = shim$2; -var clearSuspenseBoundary = shim$2; -var clearSuspenseBoundaryFromContainer = shim$2; -var errorHydratingContainer = shim$2; - -// Renderers that don't support React Scopes -// can re-export everything from this module. -function shim$1() { - throw new Error( - "The current renderer does not support React Scopes. " + - "This error is likely caused by a bug in React. " + - "Please file an issue." - ); -} // React Scopes (when unsupported) - -var prepareScopeUpdate = shim$1; -var getInstanceFromScope = shim$1; - -// Renderers that don't support hydration -// can re-export everything from this module. -function shim() { - throw new Error( - "The current renderer does not support Resources. " + - "This error is likely caused by a bug in React. " + - "Please file an issue." - ); -} // Resources (when unsupported) -var suspendResource = shim; - -var pooledTransform = new Transform(); -var NO_CONTEXT = {}; - -{ - Object.freeze(NO_CONTEXT); -} -/** Helper Methods */ + if (hiddenUpdatesForLane !== null) { + hiddenUpdates[index] = null; // "Hidden" updates are updates that were made to a hidden component. They + // have special logic associated with them because they may be entangled + // with updates that occur outside that tree. But once the outer tree + // commits, they behave like regular updates. -function addEventListeners(instance, type, listener) { - // We need to explicitly unregister before unmount. - // For this reason we need to track subscriptions. - if (!instance._listeners) { - instance._listeners = {}; - instance._subscriptions = {}; - } + for (var i = 0; i < hiddenUpdatesForLane.length; i++) { + var update = hiddenUpdatesForLane[i]; - instance._listeners[type] = listener; + if (update !== null) { + update.lane &= ~OffscreenLane; + } + } + } - if (listener) { - if (!instance._subscriptions[type]) { - instance._subscriptions[type] = instance.subscribe( - type, - createEventHandler(instance), - instance - ); - } - } else { - if (instance._subscriptions[type]) { - instance._subscriptions[type](); + lanes &= ~lane; + } - delete instance._subscriptions[type]; + if (spawnedLane !== NoLane) { + markSpawnedDeferredLane( + root, + spawnedLane, // This render finished successfully without suspending, so we don't need + // to entangle the spawned task with the parent task. + NoLanes + ); + } } - } -} -function createEventHandler(instance) { - return function handleEvent(event) { - var listener = instance._listeners[event.type]; + function markSpawnedDeferredLane(root, spawnedLane, entangledLanes) { + // This render spawned a deferred task. Mark it as pending. + root.pendingLanes |= spawnedLane; + root.suspendedLanes &= ~spawnedLane; // Entangle the spawned lane with the DeferredLane bit so that we know it + // was the result of another render. This lets us avoid a useDeferredValue + // waterfall — only the first level will defer. - if (!listener); - else if (typeof listener === "function") { - listener.call(instance, event); - } else if (listener.handleEvent) { - listener.handleEvent(event); + var spawnedLaneIndex = laneToIndex(spawnedLane); + root.entangledLanes |= spawnedLane; + root.entanglements[spawnedLaneIndex] |= + DeferredLane | // If the parent render task suspended, we must also entangle those lanes + // with the spawned task, so that the deferred task includes all the same + // updates that the parent task did. We can exclude any lane that is not + // used for updates (e.g. Offscreen). + (entangledLanes & UpdateLanes); } - }; -} -function destroyEventListeners(instance) { - if (instance._subscriptions) { - for (var type in instance._subscriptions) { - instance._subscriptions[type](); - } - } + function markRootEntangled(root, entangledLanes) { + // In addition to entangling each of the given lanes with each other, we also + // have to consider _transitive_ entanglements. For each lane that is already + // entangled with *any* of the given lanes, that lane is now transitively + // entangled with *all* the given lanes. + // + // Translated: If C is entangled with A, then entangling A with B also + // entangles C with B. + // + // If this is hard to grasp, it might help to intentionally break this + // function and look at the tests that fail in ReactTransition-test.js. Try + // commenting out one of the conditions below. + var rootEntangledLanes = (root.entangledLanes |= entangledLanes); + var entanglements = root.entanglements; + var lanes = rootEntangledLanes; - instance._subscriptions = null; - instance._listeners = null; -} + while (lanes) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; -function getScaleX(props) { - if (props.scaleX != null) { - return props.scaleX; - } else if (props.scale != null) { - return props.scale; - } else { - return 1; - } -} + if ( + // Is this one of the newly entangled lanes? + (lane & entangledLanes) | // Is this lane transitively entangled with the newly entangled lanes? + (entanglements[index] & entangledLanes) + ) { + entanglements[index] |= entangledLanes; + } -function getScaleY(props) { - if (props.scaleY != null) { - return props.scaleY; - } else if (props.scale != null) { - return props.scale; - } else { - return 1; - } -} + lanes &= ~lane; + } + } + function upgradePendingLaneToSync(root, lane) { + // Since we're upgrading the priority of the given lane, there is now pending + // sync work. + root.pendingLanes |= SyncLane; // Entangle the sync lane with the lane we're upgrading. This means SyncLane + // will not be allowed to finish without also finishing the given lane. -function isSameFont(oldFont, newFont) { - if (oldFont === newFont) { - return true; - } else if (typeof newFont === "string" || typeof oldFont === "string") { - return false; - } else { - return ( - newFont.fontSize === oldFont.fontSize && - newFont.fontStyle === oldFont.fontStyle && - newFont.fontVariant === oldFont.fontVariant && - newFont.fontWeight === oldFont.fontWeight && - newFont.fontFamily === oldFont.fontFamily - ); - } -} -/** Render Methods */ - -function applyClippingRectangleProps(instance, props) { - var prevProps = - arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - applyNodeProps(instance, props, prevProps); - instance.width = props.width; - instance.height = props.height; -} + root.entangledLanes |= SyncLane; + root.entanglements[SyncLaneIndex] |= lane; + } + function markHiddenUpdate(root, update, lane) { + var index = laneToIndex(lane); + var hiddenUpdates = root.hiddenUpdates; + var hiddenUpdatesForLane = hiddenUpdates[index]; -function applyGroupProps(instance, props) { - var prevProps = - arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - applyNodeProps(instance, props, prevProps); - instance.width = props.width; - instance.height = props.height; -} + if (hiddenUpdatesForLane === null) { + hiddenUpdates[index] = [update]; + } else { + hiddenUpdatesForLane.push(update); + } -function applyNodeProps(instance, props) { - var prevProps = - arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - var scaleX = getScaleX(props); - var scaleY = getScaleY(props); - pooledTransform - .transformTo(1, 0, 0, 1, 0, 0) - .move(props.x || 0, props.y || 0) - .rotate(props.rotation || 0, props.originX, props.originY) - .scale(scaleX, scaleY, props.originX, props.originY); - - if (props.transform != null) { - pooledTransform.transform(props.transform); - } - - if ( - instance.xx !== pooledTransform.xx || - instance.yx !== pooledTransform.yx || - instance.xy !== pooledTransform.xy || - instance.yy !== pooledTransform.yy || - instance.x !== pooledTransform.x || - instance.y !== pooledTransform.y - ) { - instance.transformTo(pooledTransform); - } - - if (props.cursor !== prevProps.cursor || props.title !== prevProps.title) { - instance.indicate(props.cursor, props.title); - } - - if (instance.blend && props.opacity !== prevProps.opacity) { - instance.blend(props.opacity == null ? 1 : props.opacity); - } - - if (props.visible !== prevProps.visible) { - if (props.visible == null || props.visible) { - instance.show(); - } else { - instance.hide(); + update.lane = lane | OffscreenLane; } - } + function getBumpedLaneForHydration(root, renderLanes) { + var renderLane = getHighestPriorityLane(renderLanes); + var lane; - for (var type in EVENT_TYPES) { - addEventListeners(instance, EVENT_TYPES[type], props[type]); - } -} + if (enableUnifiedSyncLane && (renderLane & SyncUpdateLanes) !== NoLane) { + lane = SyncHydrationLane; + } else { + switch (renderLane) { + case SyncLane: + lane = SyncHydrationLane; + break; -function applyRenderableNodeProps(instance, props) { - var prevProps = - arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - applyNodeProps(instance, props, prevProps); + case InputContinuousLane: + lane = InputContinuousHydrationLane; + break; - if (prevProps.fill !== props.fill) { - if (props.fill && props.fill.applyFill) { - props.fill.applyFill(instance); - } else { - instance.fill(props.fill); - } - } - - if ( - prevProps.stroke !== props.stroke || - prevProps.strokeWidth !== props.strokeWidth || - prevProps.strokeCap !== props.strokeCap || - prevProps.strokeJoin !== props.strokeJoin || // TODO: Consider deep check of stokeDash; may benefit VML in IE. - prevProps.strokeDash !== props.strokeDash - ) { - instance.stroke( - props.stroke, - props.strokeWidth, - props.strokeCap, - props.strokeJoin, - props.strokeDash - ); - } -} + case DefaultLane: + lane = DefaultHydrationLane; + break; -function applyShapeProps(instance, props) { - var prevProps = - arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - applyRenderableNodeProps(instance, props, prevProps); - var path = props.d || childrenAsString(props.children); - var prevDelta = instance._prevDelta; - var prevPath = instance._prevPath; - - if ( - path !== prevPath || - path.delta !== prevDelta || - prevProps.height !== props.height || - prevProps.width !== props.width - ) { - instance.draw(path, props.width, props.height); - instance._prevDelta = path.delta; - instance._prevPath = path; - } -} + case TransitionLane1: + case TransitionLane2: + case TransitionLane3: + case TransitionLane4: + case TransitionLane5: + case TransitionLane6: + case TransitionLane7: + case TransitionLane8: + case TransitionLane9: + case TransitionLane10: + case TransitionLane11: + case TransitionLane12: + case TransitionLane13: + case TransitionLane14: + case TransitionLane15: + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + lane = TransitionHydrationLane; + break; -function applyTextProps(instance, props) { - var prevProps = - arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - applyRenderableNodeProps(instance, props, prevProps); - var string = props.children; - - if ( - instance._currentString !== string || - !isSameFont(props.font, prevProps.font) || - props.alignment !== prevProps.alignment || - props.path !== prevProps.path - ) { - instance.draw(string, props.font, props.alignment, props.path); - instance._currentString = string; - } -} -function appendInitialChild(parentInstance, child) { - if (typeof child === "string") { - // Noop for string children of Text (eg {'foo'}{'bar'}) - throw new Error("Text children should already be flattened."); - } + case IdleLane: + lane = IdleHydrationLane; + break; - child.inject(parentInstance); -} -function createInstance(type, props, internalInstanceHandle) { - var instance; - - switch (type) { - case TYPES.CLIPPING_RECTANGLE: - instance = Mode$1.ClippingRectangle(); - instance._applyProps = applyClippingRectangleProps; - break; - - case TYPES.GROUP: - instance = Mode$1.Group(); - instance._applyProps = applyGroupProps; - break; - - case TYPES.SHAPE: - instance = Mode$1.Shape(); - instance._applyProps = applyShapeProps; - break; - - case TYPES.TEXT: - instance = Mode$1.Text( - props.children, - props.font, - props.alignment, - props.path - ); - instance._applyProps = applyTextProps; - break; - } + default: + // Everything else is already either a hydration lane, or shouldn't + // be retried at a hydration lane. + lane = NoLane; + break; + } + } // Check if the lane we chose is suspended. If so, that indicates that we + // already attempted and failed to hydrate at that level. Also check if we're + // already rendering that lane, which is rare but could happen. - if (!instance) { - throw new Error('ReactART does not support the type "' + type + '"'); - } + if ((lane & (root.suspendedLanes | renderLanes)) !== NoLane) { + // Give up trying to hydrate and fall back to client render. + return NoLane; + } - instance._applyProps(instance, props); + return lane; + } + function addFiberToLanesMap(root, fiber, lanes) { + if (!isDevToolsPresent) { + return; + } - return instance; -} -function createTextInstance( - text, - rootContainerInstance, - internalInstanceHandle -) { - return text; -} -function getPublicInstance(instance) { - return instance; -} -function prepareForCommit() { - // Noop - return null; -} -function resetTextContent(domElement) { - // Noop -} -function getRootHostContext() { - return NO_CONTEXT; -} -function getChildHostContext() { - return NO_CONTEXT; -} -var scheduleTimeout = setTimeout; -var cancelTimeout = clearTimeout; -var noTimeout = -1; -function shouldSetTextContent(type, props) { - return ( - typeof props.children === "string" || typeof props.children === "number" - ); -} -function getCurrentEventPriority() { - return DefaultEventPriority; -} -function shouldAttemptEagerTransition() { - return false; -} // The ART renderer is secondary to the React DOM renderer. - -var warnsIfNotActing = false; -function appendChild(parentInstance, child) { - if (child.parentNode === parentInstance) { - child.eject(); - } - - child.inject(parentInstance); -} -function appendChildToContainer(parentInstance, child) { - if (child.parentNode === parentInstance) { - child.eject(); - } - - child.inject(parentInstance); -} -function insertBefore(parentInstance, child, beforeChild) { - if (child === beforeChild) { - throw new Error("ReactART: Can not insert node before itself"); - } - - child.injectBefore(beforeChild); -} -function insertInContainerBefore(parentInstance, child, beforeChild) { - if (child === beforeChild) { - throw new Error("ReactART: Can not insert node before itself"); - } - - child.injectBefore(beforeChild); -} -function removeChild(parentInstance, child) { - destroyEventListeners(child); - child.eject(); -} -function removeChildFromContainer(parentInstance, child) { - destroyEventListeners(child); - child.eject(); -} -function commitTextUpdate(textInstance, oldText, newText) { - // Noop -} -function commitMount(instance, type, newProps) { - // Noop -} -function commitUpdate(instance, updatePayload, type, oldProps, newProps) { - instance._applyProps(instance, newProps, oldProps); -} -function hideInstance(instance) { - instance.hide(); -} -function hideTextInstance(textInstance) { - // Noop -} -function unhideInstance(instance, props) { - if (props.visible == null || props.visible) { - instance.show(); - } -} -function unhideTextInstance(textInstance, text) { - // Noop -} -function getInstanceFromNode(node) { - throw new Error("Not implemented."); -} -function preloadInstance(type, props) { - // Return true to indicate it's already loaded - return true; -} -function waitForCommitToBeReady() { - return null; -} + var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; -var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher; -var prefix; -function describeBuiltInComponentFrame(name, source, ownerFn) { - { - if (prefix === undefined) { - // Extract the VM specific prefix used by each line. - try { - throw Error(); - } catch (x) { - var match = x.stack.trim().match(/\n( *(at )?)/); - prefix = (match && match[1]) || ""; + while (lanes > 0) { + var index = laneToIndex(lanes); + var lane = 1 << index; + var updaters = pendingUpdatersLaneMap[index]; + updaters.add(fiber); + lanes &= ~lane; + } + } + function movePendingFibersToMemoized(root, lanes) { + if (!isDevToolsPresent) { + return; } - } // We use the prefix to ensure our stacks line up with native stack frames. - return "\n" + prefix + name; - } -} -var reentry = false; -var componentFrameCache; + var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; + var memoizedUpdaters = root.memoizedUpdaters; -{ - var PossiblyWeakMap$2 = typeof WeakMap === "function" ? WeakMap : Map; - componentFrameCache = new PossiblyWeakMap$2(); -} + while (lanes > 0) { + var index = laneToIndex(lanes); + var lane = 1 << index; + var updaters = pendingUpdatersLaneMap[index]; -function describeNativeComponentFrame(fn, construct) { - // If something asked for a stack inside a fake render, it should get ignored. - if (!fn || reentry) { - return ""; - } + if (updaters.size > 0) { + updaters.forEach(function (fiber) { + var alternate = fiber.alternate; - { - var frame = componentFrameCache.get(fn); + if (alternate === null || !memoizedUpdaters.has(alternate)) { + memoizedUpdaters.add(fiber); + } + }); + updaters.clear(); + } - if (frame !== undefined) { - return frame; + lanes &= ~lane; + } } - } - - var control; - reentry = true; - var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. - - Error.prepareStackTrace = undefined; - var previousDispatcher; + function addTransitionToLanesMap(root, transition, lane) { + if (enableTransitionTracing) { + var transitionLanesMap = root.transitionLanes; + var index = laneToIndex(lane); + var transitions = transitionLanesMap[index]; - { - previousDispatcher = ReactCurrentDispatcher$2.current; // Set the dispatcher in DEV because this might be call in the render function - // for warnings. + if (transitions === null) { + transitions = new Set(); + } - ReactCurrentDispatcher$2.current = null; - disableLogs(); - } + transitions.add(transition); + transitionLanesMap[index] = transitions; + } + } + function getTransitionsForLanes(root, lanes) { + if (!enableTransitionTracing) { + return null; + } - try { - // This should throw. - if (construct) { - // Something should be setting the props in the constructor. - var Fake = function () { - throw Error(); - }; // $FlowFixMe[prop-missing] + var transitionsForLanes = []; - Object.defineProperty(Fake.prototype, "props", { - set: function () { - // We use a throwing setter instead of frozen or non-writable props - // because that won't throw in a non-strict mode function. - throw Error(); - } - }); + while (lanes > 0) { + var index = laneToIndex(lanes); + var lane = 1 << index; + var transitions = root.transitionLanes[index]; - if (typeof Reflect === "object" && Reflect.construct) { - // We construct a different control for this case to include any extra - // frames added by the construct call. - try { - Reflect.construct(Fake, []); - } catch (x) { - control = x; + if (transitions !== null) { + transitions.forEach(function (transition) { + transitionsForLanes.push(transition); + }); } - Reflect.construct(fn, [], Fake); - } else { - try { - Fake.call(); - } catch (x) { - control = x; - } // $FlowFixMe[prop-missing] found when upgrading Flow + lanes &= ~lane; + } - fn.call(Fake.prototype); + if (transitionsForLanes.length === 0) { + return null; } - } else { - try { - throw Error(); - } catch (x) { - control = x; - } // TODO(luna): This will currently only throw if the function component - // tries to access React/ReactDOM/props. We should probably make this throw - // in simple components too - - var maybePromise = fn(); // If the function component returns a promise, it's likely an async - // component, which we don't yet support. Attach a noop catch handler to - // silence the error. - // TODO: Implement component stacks for async client components? - - if (maybePromise && typeof maybePromise.catch === "function") { - maybePromise.catch(function () {}); - } - } - } catch (sample) { - // This is inlined manually because closure doesn't do it for us. - if (sample && control && typeof sample.stack === "string") { - // This extracts the first frame from the sample that isn't also in the control. - // Skipping one frame that we assume is the frame that calls the two. - var sampleLines = sample.stack.split("\n"); - var controlLines = control.stack.split("\n"); - var s = sampleLines.length - 1; - var c = controlLines.length - 1; - - while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { - // We expect at least one stack frame to be shared. - // Typically this will be the root most one. However, stack frames may be - // cut off due to maximum stack limits. In this case, one maybe cut off - // earlier than the other. We assume that the sample is longer or the same - // and there for cut off earlier. So we should find the root most frame in - // the sample somewhere in the control. - c--; - } - - for (; s >= 1 && c >= 0; s--, c--) { - // Next we find the first one that isn't the same which should be the - // frame that called our sample function and the control. - if (sampleLines[s] !== controlLines[c]) { - // In V8, the first line is describing the message but other VMs don't. - // If we're about to return the first line, and the control is also on the same - // line, that's a pretty good indicator that our sample threw at same line as - // the control. I.e. before we entered the sample frame. So we ignore this result. - // This can happen if you passed a class to function component, or non-function. - if (s !== 1 || c !== 1) { - do { - s--; - c--; // We may still have similar intermediate frames from the construct call. - // The next one that isn't the same should be our match though. - - if (c < 0 || sampleLines[s] !== controlLines[c]) { - // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. - var _frame = "\n" + sampleLines[s].replace(" at new ", " at "); // If our component frame is labeled "" - // but we have a user-provided "displayName" - // splice it in to make the stack more readable. - - if (fn.displayName && _frame.includes("")) { - _frame = _frame.replace("", fn.displayName); - } - { - if (typeof fn === "function") { - componentFrameCache.set(fn, _frame); - } - } // Return the line we found. + return transitionsForLanes; + } + function clearTransitionsForLanes(root, lanes) { + if (!enableTransitionTracing) { + return; + } - return _frame; - } - } while (s >= 1 && c >= 0); - } + while (lanes > 0) { + var index = laneToIndex(lanes); + var lane = 1 << index; + var transitions = root.transitionLanes[index]; - break; + if (transitions !== null) { + root.transitionLanes[index] = null; } + + lanes &= ~lane; } } - } finally { - reentry = false; - { - ReactCurrentDispatcher$2.current = previousDispatcher; - reenableLogs(); + var DiscreteEventPriority = SyncLane; + var ContinuousEventPriority = InputContinuousLane; + var DefaultEventPriority = DefaultLane; + var IdleEventPriority = IdleLane; + var currentUpdatePriority = NoLane; + function getCurrentUpdatePriority() { + return currentUpdatePriority; + } + function setCurrentUpdatePriority(newPriority) { + currentUpdatePriority = newPriority; } + function higherEventPriority(a, b) { + return a !== 0 && a < b ? a : b; + } + function lowerEventPriority(a, b) { + return a === 0 || a > b ? a : b; + } + function isHigherEventPriority(a, b) { + return a !== 0 && a < b; + } + function lanesToEventPriority(lanes) { + var lane = getHighestPriorityLane(lanes); + + if (!isHigherEventPriority(DiscreteEventPriority, lane)) { + return DiscreteEventPriority; + } - Error.prepareStackTrace = previousPrepareStackTrace; - } // Fallback to just using the name if we couldn't make it throw. + if (!isHigherEventPriority(ContinuousEventPriority, lane)) { + return ContinuousEventPriority; + } - var name = fn ? fn.displayName || fn.name : ""; - var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ""; + if (includesNonIdleWork(lane)) { + return DefaultEventPriority; + } - { - if (typeof fn === "function") { - componentFrameCache.set(fn, syntheticFrame); + return IdleEventPriority; } - } - return syntheticFrame; -} + // Renderers that don't support hydration + // can re-export everything from this module. + function shim$2() { + throw new Error( + "The current renderer does not support hydration. " + + "This error is likely caused by a bug in React. " + + "Please file an issue." + ); + } // Hydration (when unsupported) + var isSuspenseInstancePending = shim$2; + var isSuspenseInstanceFallback = shim$2; + var getSuspenseInstanceFallbackErrorDetails = shim$2; + var registerSuspenseInstanceRetry = shim$2; + var clearSuspenseBoundary = shim$2; + var clearSuspenseBoundaryFromContainer = shim$2; + var errorHydratingContainer = shim$2; + + // Renderers that don't support React Scopes + // can re-export everything from this module. + function shim$1() { + throw new Error( + "The current renderer does not support React Scopes. " + + "This error is likely caused by a bug in React. " + + "Please file an issue." + ); + } // React Scopes (when unsupported) -function describeClassComponentFrame(ctor, source, ownerFn) { - { - return describeNativeComponentFrame(ctor, true); - } -} -function describeFunctionComponentFrame(fn, source, ownerFn) { - { - return describeNativeComponentFrame(fn, false); - } -} + var prepareScopeUpdate = shim$1; + var getInstanceFromScope = shim$1; -function shouldConstruct$1(Component) { - var prototype = Component.prototype; - return !!(prototype && prototype.isReactComponent); -} + // Renderers that don't support hydration + // can re-export everything from this module. + function shim() { + throw new Error( + "The current renderer does not support Resources. " + + "This error is likely caused by a bug in React. " + + "Please file an issue." + ); + } // Resources (when unsupported) + var suspendResource = shim; -function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { - if (type == null) { - return ""; - } + var pooledTransform = new Transform(); + var NO_CONTEXT = {}; - if (typeof type === "function") { { - return describeNativeComponentFrame(type, shouldConstruct$1(type)); + Object.freeze(NO_CONTEXT); } - } + /** Helper Methods */ - if (typeof type === "string") { - return describeBuiltInComponentFrame(type); - } + function addEventListeners(instance, type, listener) { + // We need to explicitly unregister before unmount. + // For this reason we need to track subscriptions. + if (!instance._listeners) { + instance._listeners = {}; + instance._subscriptions = {}; + } - switch (type) { - case REACT_SUSPENSE_TYPE: - return describeBuiltInComponentFrame("Suspense"); + instance._listeners[type] = listener; - case REACT_SUSPENSE_LIST_TYPE: - return describeBuiltInComponentFrame("SuspenseList"); - } + if (listener) { + if (!instance._subscriptions[type]) { + instance._subscriptions[type] = instance.subscribe( + type, + createEventHandler(instance), + instance + ); + } + } else { + if (instance._subscriptions[type]) { + instance._subscriptions[type](); - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_FORWARD_REF_TYPE: - return describeFunctionComponentFrame(type.render); + delete instance._subscriptions[type]; + } + } + } - case REACT_MEMO_TYPE: - // Memo may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); + function createEventHandler(instance) { + return function handleEvent(event) { + var listener = instance._listeners[event.type]; - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + if (!listener); + else if (typeof listener === "function") { + listener.call(instance, event); + } else if (listener.handleEvent) { + listener.handleEvent(event); + } + }; + } - try { - // Lazy may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV( - init(payload), - source, - ownerFn - ); - } catch (x) {} + function destroyEventListeners(instance) { + if (instance._subscriptions) { + for (var type in instance._subscriptions) { + instance._subscriptions[type](); + } } + + instance._subscriptions = null; + instance._listeners = null; } - } - return ""; -} + function getScaleX(props) { + if (props.scaleX != null) { + return props.scaleX; + } else if (props.scale != null) { + return props.scale; + } else { + return 1; + } + } -// $FlowFixMe[method-unbinding] -var hasOwnProperty = Object.prototype.hasOwnProperty; + function getScaleY(props) { + if (props.scaleY != null) { + return props.scaleY; + } else if (props.scale != null) { + return props.scale; + } else { + return 1; + } + } -var loggedTypeFailures = {}; -var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; + function isSameFont(oldFont, newFont) { + if (oldFont === newFont) { + return true; + } else if (typeof newFont === "string" || typeof oldFont === "string") { + return false; + } else { + return ( + newFont.fontSize === oldFont.fontSize && + newFont.fontStyle === oldFont.fontStyle && + newFont.fontVariant === oldFont.fontVariant && + newFont.fontWeight === oldFont.fontWeight && + newFont.fontFamily === oldFont.fontFamily + ); + } + } + /** Render Methods */ -function setCurrentlyValidatingElement(element) { - { - if (element) { - var owner = element._owner; - var stack = describeUnknownElementTypeFrameInDEV( - element.type, - element._source, - owner ? owner.type : null - ); - ReactDebugCurrentFrame$1.setExtraStackFrame(stack); - } else { - ReactDebugCurrentFrame$1.setExtraStackFrame(null); + function applyClippingRectangleProps(instance, props) { + var prevProps = + arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + applyNodeProps(instance, props, prevProps); + instance.width = props.width; + instance.height = props.height; } - } -} -function checkPropTypes(typeSpecs, values, location, componentName, element) { - { - // $FlowFixMe[incompatible-use] This is okay but Flow doesn't know it. - var has = Function.call.bind(hasOwnProperty); + function applyGroupProps(instance, props) { + var prevProps = + arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + applyNodeProps(instance, props, prevProps); + instance.width = props.width; + instance.height = props.height; + } - for (var typeSpecName in typeSpecs) { - if (has(typeSpecs, typeSpecName)) { - var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to - // fail the render phase where it didn't fail before. So we log it. - // After these have been cleaned up, we'll let them throw. + function applyNodeProps(instance, props) { + var prevProps = + arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + var scaleX = getScaleX(props); + var scaleY = getScaleY(props); + pooledTransform + .transformTo(1, 0, 0, 1, 0, 0) + .move(props.x || 0, props.y || 0) + .rotate(props.rotation || 0, props.originX, props.originY) + .scale(scaleX, scaleY, props.originX, props.originY); - try { - // This is intentionally an invariant that gets caught. It's the same - // behavior as without this statement except with a better message. - if (typeof typeSpecs[typeSpecName] !== "function") { - // eslint-disable-next-line react-internal/prod-error-codes - 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`." - ); - err.name = "Invariant Violation"; - throw err; - } + if (props.transform != null) { + pooledTransform.transform(props.transform); + } - error$1 = typeSpecs[typeSpecName]( - values, - typeSpecName, - componentName, - location, - null, - "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" - ); - } catch (ex) { - error$1 = ex; - } + if ( + instance.xx !== pooledTransform.xx || + instance.yx !== pooledTransform.yx || + instance.xy !== pooledTransform.xy || + instance.yy !== pooledTransform.yy || + instance.x !== pooledTransform.x || + instance.y !== pooledTransform.y + ) { + instance.transformTo(pooledTransform); + } - if (error$1 && !(error$1 instanceof Error)) { - setCurrentlyValidatingElement(element); + if ( + props.cursor !== prevProps.cursor || + props.title !== prevProps.title + ) { + instance.indicate(props.cursor, props.title); + } - 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 - ); + if (instance.blend && props.opacity !== prevProps.opacity) { + instance.blend(props.opacity == null ? 1 : props.opacity); + } - setCurrentlyValidatingElement(null); + if (props.visible !== prevProps.visible) { + if (props.visible == null || props.visible) { + instance.show(); + } else { + instance.hide(); } + } - if ( - error$1 instanceof Error && - !(error$1.message in loggedTypeFailures) - ) { - // Only monitor this failure once because there tends to be a lot of the - // same error. - loggedTypeFailures[error$1.message] = true; - setCurrentlyValidatingElement(element); + for (var type in EVENT_TYPES) { + addEventListeners(instance, EVENT_TYPES[type], props[type]); + } + } - error("Failed %s type: %s", location, error$1.message); + function applyRenderableNodeProps(instance, props) { + var prevProps = + arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + applyNodeProps(instance, props, prevProps); - setCurrentlyValidatingElement(null); + if (prevProps.fill !== props.fill) { + if (props.fill && props.fill.applyFill) { + props.fill.applyFill(instance); + } else { + instance.fill(props.fill); } } - } - } -} -var valueStack = []; -var fiberStack; + if ( + prevProps.stroke !== props.stroke || + prevProps.strokeWidth !== props.strokeWidth || + prevProps.strokeCap !== props.strokeCap || + prevProps.strokeJoin !== props.strokeJoin || // TODO: Consider deep check of stokeDash; may benefit VML in IE. + prevProps.strokeDash !== props.strokeDash + ) { + instance.stroke( + props.stroke, + props.strokeWidth, + props.strokeCap, + props.strokeJoin, + props.strokeDash + ); + } + } -{ - fiberStack = []; -} + function applyShapeProps(instance, props) { + var prevProps = + arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + applyRenderableNodeProps(instance, props, prevProps); + var path = props.d || childrenAsString(props.children); + var prevDelta = instance._prevDelta; + var prevPath = instance._prevPath; -var index = -1; + if ( + path !== prevPath || + path.delta !== prevDelta || + prevProps.height !== props.height || + prevProps.width !== props.width + ) { + instance.draw(path, props.width, props.height); + instance._prevDelta = path.delta; + instance._prevPath = path; + } + } -function createCursor(defaultValue) { - return { - current: defaultValue - }; -} + function applyTextProps(instance, props) { + var prevProps = + arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + applyRenderableNodeProps(instance, props, prevProps); + var string = props.children; -function pop(cursor, fiber) { - if (index < 0) { - { - error("Unexpected pop."); + if ( + instance._currentString !== string || + !isSameFont(props.font, prevProps.font) || + props.alignment !== prevProps.alignment || + props.path !== prevProps.path + ) { + instance.draw(string, props.font, props.alignment, props.path); + instance._currentString = string; + } } + function appendInitialChild(parentInstance, child) { + if (typeof child === "string") { + // Noop for string children of Text (eg {'foo'}{'bar'}) + throw new Error("Text children should already be flattened."); + } - return; - } - - { - if (fiber !== fiberStack[index]) { - error("Unexpected Fiber popped."); + child.inject(parentInstance); } - } + function createInstance(type, props, internalInstanceHandle) { + var instance; - cursor.current = valueStack[index]; - valueStack[index] = null; + switch (type) { + case TYPES.CLIPPING_RECTANGLE: + instance = Mode$1.ClippingRectangle(); + instance._applyProps = applyClippingRectangleProps; + break; - { - fiberStack[index] = null; - } + case TYPES.GROUP: + instance = Mode$1.Group(); + instance._applyProps = applyGroupProps; + break; - index--; -} + case TYPES.SHAPE: + instance = Mode$1.Shape(); + instance._applyProps = applyShapeProps; + break; -function push(cursor, value, fiber) { - index++; - valueStack[index] = cursor.current; + case TYPES.TEXT: + instance = Mode$1.Text( + props.children, + props.font, + props.alignment, + props.path + ); + instance._applyProps = applyTextProps; + break; + } - { - fiberStack[index] = fiber; - } + if (!instance) { + throw new Error('ReactART does not support the type "' + type + '"'); + } - cursor.current = value; -} + instance._applyProps(instance, props); -var emptyContextObject = {}; + return instance; + } + function createTextInstance( + text, + rootContainerInstance, + internalInstanceHandle + ) { + return text; + } + function getPublicInstance(instance) { + return instance; + } + function prepareForCommit() { + // Noop + return null; + } + function resetTextContent(domElement) { + // Noop + } + function getRootHostContext() { + return NO_CONTEXT; + } + function getChildHostContext() { + return NO_CONTEXT; + } + var scheduleTimeout = setTimeout; + var cancelTimeout = clearTimeout; + var noTimeout = -1; + function shouldSetTextContent(type, props) { + return ( + typeof props.children === "string" || typeof props.children === "number" + ); + } + function getCurrentEventPriority() { + return DefaultEventPriority; + } + function shouldAttemptEagerTransition() { + return false; + } // The ART renderer is secondary to the React DOM renderer. -{ - Object.freeze(emptyContextObject); -} // A cursor to the current merged context object on the stack. + var warnsIfNotActing = false; + function appendChild(parentInstance, child) { + if (child.parentNode === parentInstance) { + child.eject(); + } -function hasContextChanged() { - { - return false; - } -} + child.inject(parentInstance); + } + function appendChildToContainer(parentInstance, child) { + if (child.parentNode === parentInstance) { + child.eject(); + } -function isContextProvider(type) { - { - return false; - } -} + child.inject(parentInstance); + } + function insertBefore(parentInstance, child, beforeChild) { + if (child === beforeChild) { + throw new Error("ReactART: Can not insert node before itself"); + } -function processChildContext(fiber, type, parentContext) { - { - return parentContext; - } -} + child.injectBefore(beforeChild); + } + function insertInContainerBefore(parentInstance, child, beforeChild) { + if (child === beforeChild) { + throw new Error("ReactART: Can not insert node before itself"); + } -function findCurrentUnmaskedContext(fiber) { - { - return emptyContextObject; - } -} + child.injectBefore(beforeChild); + } + function removeChild(parentInstance, child) { + destroyEventListeners(child); + child.eject(); + } + function removeChildFromContainer(parentInstance, child) { + destroyEventListeners(child); + child.eject(); + } + function commitTextUpdate(textInstance, oldText, newText) { + // Noop + } + function commitMount(instance, type, newProps) { + // Noop + } + function commitUpdate(instance, updatePayload, type, oldProps, newProps) { + instance._applyProps(instance, newProps, oldProps); + } + function hideInstance(instance) { + instance.hide(); + } + function hideTextInstance(textInstance) { + // Noop + } + function unhideInstance(instance, props) { + if (props.visible == null || props.visible) { + instance.show(); + } + } + function unhideTextInstance(textInstance, text) { + // Noop + } + function getInstanceFromNode(node) { + throw new Error("Not implemented."); + } + function preloadInstance(type, props) { + // Return true to indicate it's already loaded + return true; + } + function waitForCommitToBeReady() { + return null; + } -// We use the existence of the state object as an indicator that the component -// is hidden. -var OffscreenVisible = - /* */ - 1; -var OffscreenDetached = - /* */ - 2; -var OffscreenPassiveEffectsConnected = - /* */ - 4; -function isOffscreenManual(offscreenFiber) { - return ( - offscreenFiber.memoizedProps !== null && - offscreenFiber.memoizedProps.mode === "manual" - ); -} + var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher; + var prefix; + function describeBuiltInComponentFrame(name, source, ownerFn) { + { + if (prefix === undefined) { + // Extract the VM specific prefix used by each line. + try { + throw Error(); + } catch (x) { + var match = x.stack.trim().match(/\n( *(at )?)/); + prefix = (match && match[1]) || ""; + } + } // We use the prefix to ensure our stacks line up with native stack frames. -/** - * inlined Object.is polyfill to avoid requiring consumers ship their own - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is - */ -function is(x, y) { - return ( - (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare - ); -} + return "\n" + prefix + name; + } + } + var reentry = false; + var componentFrameCache; -var objectIs = typeof Object.is === "function" ? Object.is : is; // $FlowFixMe[method-unbinding] + { + var PossiblyWeakMap$2 = typeof WeakMap === "function" ? WeakMap : Map; + componentFrameCache = new PossiblyWeakMap$2(); + } -var nativeConsole = console; -var nativeConsoleLog = null; -var pendingGroupArgs = []; -var printedGroupIndex = -1; + function describeNativeComponentFrame(fn, construct) { + // If something asked for a stack inside a fake render, it should get ignored. + if (!fn || reentry) { + return ""; + } -function formatLanes(laneOrLanes) { - return "0b" + laneOrLanes.toString(2).padStart(31, "0"); -} + { + var frame = componentFrameCache.get(fn); -function group() { - for ( - var _len = arguments.length, groupArgs = new Array(_len), _key = 0; - _key < _len; - _key++ - ) { - groupArgs[_key] = arguments[_key]; - } - - pendingGroupArgs.push(groupArgs); - - if (nativeConsoleLog === null) { - nativeConsoleLog = nativeConsole.log; - nativeConsole.log = log; - } -} + if (frame !== undefined) { + return frame; + } + } -function groupEnd() { - pendingGroupArgs.pop(); + var control; + reentry = true; + var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. - while (printedGroupIndex >= pendingGroupArgs.length) { - nativeConsole.groupEnd(); - printedGroupIndex--; - } + Error.prepareStackTrace = undefined; + var previousDispatcher; - if (pendingGroupArgs.length === 0) { - nativeConsole.log = nativeConsoleLog; - nativeConsoleLog = null; - } -} + { + previousDispatcher = ReactCurrentDispatcher$2.current; // Set the dispatcher in DEV because this might be call in the render function + // for warnings. -function log() { - if (printedGroupIndex < pendingGroupArgs.length - 1) { - for (var i = printedGroupIndex + 1; i < pendingGroupArgs.length; i++) { - var groupArgs = pendingGroupArgs[i]; - nativeConsole.group.apply(nativeConsole, groupArgs); - } + ReactCurrentDispatcher$2.current = null; + disableLogs(); + } - printedGroupIndex = pendingGroupArgs.length - 1; - } + try { + // This should throw. + if (construct) { + // Something should be setting the props in the constructor. + var Fake = function () { + throw Error(); + }; // $FlowFixMe[prop-missing] + + Object.defineProperty(Fake.prototype, "props", { + set: function () { + // We use a throwing setter instead of frozen or non-writable props + // because that won't throw in a non-strict mode function. + throw Error(); + } + }); - if (typeof nativeConsoleLog === "function") { - nativeConsoleLog.apply(void 0, arguments); - } else { - nativeConsole.log.apply(nativeConsole, arguments); - } -} + if (typeof Reflect === "object" && Reflect.construct) { + // We construct a different control for this case to include any extra + // frames added by the construct call. + try { + Reflect.construct(Fake, []); + } catch (x) { + control = x; + } -var REACT_LOGO_STYLE = - "background-color: #20232a; color: #61dafb; padding: 0 2px;"; -function logCommitStarted(lanes) { - { - if (enableDebugTracing) { - group( - "%c\u269B\uFE0F%c commit%c (" + formatLanes(lanes) + ")", - REACT_LOGO_STYLE, - "", - "font-weight: normal;" - ); - } - } -} -function logCommitStopped() { - { - if (enableDebugTracing) { - groupEnd(); - } - } -} -var PossiblyWeakMap$1 = typeof WeakMap === "function" ? WeakMap : Map; // $FlowFixMe[incompatible-type]: Flow cannot handle polymorphic WeakMaps + Reflect.construct(fn, [], Fake); + } else { + try { + Fake.call(); + } catch (x) { + control = x; + } // $FlowFixMe[prop-missing] found when upgrading Flow -var wakeableIDs = new PossiblyWeakMap$1(); -var wakeableID = 0; + fn.call(Fake.prototype); + } + } else { + try { + throw Error(); + } catch (x) { + control = x; + } // TODO(luna): This will currently only throw if the function component + // tries to access React/ReactDOM/props. We should probably make this throw + // in simple components too + + var maybePromise = fn(); // If the function component returns a promise, it's likely an async + // component, which we don't yet support. Attach a noop catch handler to + // silence the error. + // TODO: Implement component stacks for async client components? + + if (maybePromise && typeof maybePromise.catch === "function") { + maybePromise.catch(function () {}); + } + } + } catch (sample) { + // This is inlined manually because closure doesn't do it for us. + if (sample && control && typeof sample.stack === "string") { + // This extracts the first frame from the sample that isn't also in the control. + // Skipping one frame that we assume is the frame that calls the two. + var sampleLines = sample.stack.split("\n"); + var controlLines = control.stack.split("\n"); + var s = sampleLines.length - 1; + var c = controlLines.length - 1; + + while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { + // We expect at least one stack frame to be shared. + // Typically this will be the root most one. However, stack frames may be + // cut off due to maximum stack limits. In this case, one maybe cut off + // earlier than the other. We assume that the sample is longer or the same + // and there for cut off earlier. So we should find the root most frame in + // the sample somewhere in the control. + c--; + } -function getWakeableID(wakeable) { - if (!wakeableIDs.has(wakeable)) { - wakeableIDs.set(wakeable, wakeableID++); - } + for (; s >= 1 && c >= 0; s--, c--) { + // Next we find the first one that isn't the same which should be the + // frame that called our sample function and the control. + if (sampleLines[s] !== controlLines[c]) { + // In V8, the first line is describing the message but other VMs don't. + // If we're about to return the first line, and the control is also on the same + // line, that's a pretty good indicator that our sample threw at same line as + // the control. I.e. before we entered the sample frame. So we ignore this result. + // This can happen if you passed a class to function component, or non-function. + if (s !== 1 || c !== 1) { + do { + s--; + c--; // We may still have similar intermediate frames from the construct call. + // The next one that isn't the same should be our match though. + + if (c < 0 || sampleLines[s] !== controlLines[c]) { + // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. + var _frame = + "\n" + sampleLines[s].replace(" at new ", " at "); // If our component frame is labeled "" + // but we have a user-provided "displayName" + // splice it in to make the stack more readable. + + if (fn.displayName && _frame.includes("")) { + _frame = _frame.replace("", fn.displayName); + } - return wakeableIDs.get(wakeable); -} + { + if (typeof fn === "function") { + componentFrameCache.set(fn, _frame); + } + } // Return the line we found. -function logComponentSuspended(componentName, wakeable) { - { - if (enableDebugTracing) { - var id = getWakeableID(wakeable); - var display = wakeable.displayName || wakeable; - log( - "%c\u269B\uFE0F%c " + componentName + " suspended", - REACT_LOGO_STYLE, - "color: #80366d; font-weight: bold;", - id, - display - ); - wakeable.then( - function () { - log( - "%c\u269B\uFE0F%c " + componentName + " resolved", - REACT_LOGO_STYLE, - "color: #80366d; font-weight: bold;", - id, - display - ); - }, - function () { - log( - "%c\u269B\uFE0F%c " + componentName + " rejected", - REACT_LOGO_STYLE, - "color: #80366d; font-weight: bold;", - id, - display - ); - } - ); - } - } -} -function logLayoutEffectsStarted(lanes) { - { - if (enableDebugTracing) { - group( - "%c\u269B\uFE0F%c layout effects%c (" + formatLanes(lanes) + ")", - REACT_LOGO_STYLE, - "", - "font-weight: normal;" - ); - } - } -} -function logLayoutEffectsStopped() { - { - if (enableDebugTracing) { - groupEnd(); - } - } -} -function logPassiveEffectsStarted(lanes) { - { - if (enableDebugTracing) { - group( - "%c\u269B\uFE0F%c passive effects%c (" + formatLanes(lanes) + ")", - REACT_LOGO_STYLE, - "", - "font-weight: normal;" - ); - } - } -} -function logPassiveEffectsStopped() { - { - if (enableDebugTracing) { - groupEnd(); - } - } -} -function logRenderStarted(lanes) { - { - if (enableDebugTracing) { - group( - "%c\u269B\uFE0F%c render%c (" + formatLanes(lanes) + ")", - REACT_LOGO_STYLE, - "", - "font-weight: normal;" - ); - } - } -} -function logRenderStopped() { - { - if (enableDebugTracing) { - groupEnd(); - } - } -} -function logForceUpdateScheduled(componentName, lane) { - { - if (enableDebugTracing) { - log( - "%c\u269B\uFE0F%c " + - componentName + - " forced update %c(" + - formatLanes(lane) + - ")", - REACT_LOGO_STYLE, - "color: #db2e1f; font-weight: bold;", - "" - ); - } - } -} -function logStateUpdateScheduled(componentName, lane, payloadOrAction) { - { - if (enableDebugTracing) { - log( - "%c\u269B\uFE0F%c " + - componentName + - " updated state %c(" + - formatLanes(lane) + - ")", - REACT_LOGO_STYLE, - "color: #01a252; font-weight: bold;", - "", - payloadOrAction - ); - } - } -} - -// This is imported by the event replaying implementation in React DOM. It's -// in a separate file to break a circular dependency between the renderer and -// the reconciler. -function isRootDehydrated(root) { - var currentState = root.current.memoizedState; - return currentState.isDehydrated; -} - -var contextStackCursor = createCursor(null); -var contextFiberStackCursor = createCursor(null); -var rootInstanceStackCursor = createCursor(null); // Represents the nearest host transition provider (in React DOM, a ) - -function requiredContext(c) { - { - if (c === null) { - error( - "Expected host context to exist. This error is likely caused by a bug " + - "in React. Please file an issue." - ); - } - } - - return c; -} - -function getRootHostContainer() { - var rootInstance = requiredContext(rootInstanceStackCursor.current); - return rootInstance; -} + return _frame; + } + } while (s >= 1 && c >= 0); + } -function pushHostContainer(fiber, nextRootInstance) { - // Push current root instance onto the stack; - // This allows us to reset root when portals are popped. - push(rootInstanceStackCursor, nextRootInstance, fiber); // Track the context and the Fiber that provided it. - // This enables us to pop only Fibers that provide unique contexts. + break; + } + } + } + } finally { + reentry = false; - push(contextFiberStackCursor, fiber, fiber); // Finally, we need to push the host context to the stack. - // However, we can't just call getRootHostContext() and push it because - // we'd have a different number of entries on the stack depending on - // whether getRootHostContext() throws somewhere in renderer code or not. - // So we push an empty value first. This lets us safely unwind on errors. + { + ReactCurrentDispatcher$2.current = previousDispatcher; + reenableLogs(); + } - push(contextStackCursor, null, fiber); - var nextRootContext = getRootHostContext(); // Now that we know this function doesn't throw, replace it. + Error.prepareStackTrace = previousPrepareStackTrace; + } // Fallback to just using the name if we couldn't make it throw. - pop(contextStackCursor, fiber); - push(contextStackCursor, nextRootContext, fiber); -} + var name = fn ? fn.displayName || fn.name : ""; + var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ""; -function popHostContainer(fiber) { - pop(contextStackCursor, fiber); - pop(contextFiberStackCursor, fiber); - pop(rootInstanceStackCursor, fiber); -} + { + if (typeof fn === "function") { + componentFrameCache.set(fn, syntheticFrame); + } + } -function getHostContext() { - var context = requiredContext(contextStackCursor.current); - return context; -} + return syntheticFrame; + } -function pushHostContext(fiber) { - var context = requiredContext(contextStackCursor.current); - var nextContext = getChildHostContext(); // Don't push this Fiber's context unless it's unique. + function describeClassComponentFrame(ctor, source, ownerFn) { + { + return describeNativeComponentFrame(ctor, true); + } + } + function describeFunctionComponentFrame(fn, source, ownerFn) { + { + return describeNativeComponentFrame(fn, false); + } + } - if (context !== nextContext) { - // Track the context and the Fiber that provided it. - // This enables us to pop only Fibers that provide unique contexts. - push(contextFiberStackCursor, fiber, fiber); - push(contextStackCursor, nextContext, fiber); - } -} + function shouldConstruct$1(Component) { + var prototype = Component.prototype; + return !!(prototype && prototype.isReactComponent); + } -function popHostContext(fiber) { - if (contextFiberStackCursor.current === fiber) { - // Do not pop unless this Fiber provided the current context. - // pushHostContext() only pushes Fibers that provide unique contexts. - pop(contextStackCursor, fiber); - pop(contextFiberStackCursor, fiber); - } -} + function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { + if (type == null) { + return ""; + } -var isHydrating = false; // This flag allows for warning supression when we expect there to be mismatches -// due to earlier mismatches or a suspended fiber. + if (typeof type === "function") { + { + return describeNativeComponentFrame(type, shouldConstruct$1(type)); + } + } -var didSuspendOrErrorDEV = false; // Hydration errors that were thrown inside this boundary + if (typeof type === "string") { + return describeBuiltInComponentFrame(type); + } -var hydrationErrors = null; -function didSuspendOrErrorWhileHydratingDEV() { - { - return didSuspendOrErrorDEV; - } -} + switch (type) { + case REACT_SUSPENSE_TYPE: + return describeBuiltInComponentFrame("Suspense"); -function prepareToHydrateHostInstance(fiber, hostContext) { - { - throw new Error( - "Expected prepareToHydrateHostInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } -} + case REACT_SUSPENSE_LIST_TYPE: + return describeBuiltInComponentFrame("SuspenseList"); + } -function prepareToHydrateHostTextInstance(fiber) { - { - throw new Error( - "Expected prepareToHydrateHostTextInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } -} + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_FORWARD_REF_TYPE: + return describeFunctionComponentFrame(type.render); -function prepareToHydrateHostSuspenseInstance(fiber) { - { - throw new Error( - "Expected prepareToHydrateHostSuspenseInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - } -} + case REACT_MEMO_TYPE: + // Memo may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + type.type, + source, + ownerFn + ); -function popHydrationState(fiber) { - { - return false; - } -} + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; -function upgradeHydrationErrorsToRecoverable() { - if (hydrationErrors !== null) { - // Successfully completed a forced client render. The errors that occurred - // during the hydration attempt are now recovered. We will log them in - // commit phase, once the entire tree has finished. - queueRecoverableErrors(hydrationErrors); - hydrationErrors = null; - } -} + try { + // Lazy may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + init(payload), + source, + ownerFn + ); + } catch (x) {} + } + } + } -function getIsHydrating() { - return isHydrating; -} + return ""; + } -function queueHydrationError(error) { - if (hydrationErrors === null) { - hydrationErrors = [error]; - } else { - hydrationErrors.push(error); - } -} + // $FlowFixMe[method-unbinding] + var hasOwnProperty = Object.prototype.hasOwnProperty; -// we wait until the current render is over (either finished or interrupted) -// before adding it to the fiber/hook queue. Push to this array so we can -// access the queue, fiber, update, et al later. - -var concurrentQueues = []; -var concurrentQueuesIndex = 0; -var concurrentlyUpdatedLanes = NoLanes; -function finishQueueingConcurrentUpdates() { - var endIndex = concurrentQueuesIndex; - concurrentQueuesIndex = 0; - concurrentlyUpdatedLanes = NoLanes; - var i = 0; - - while (i < endIndex) { - var fiber = concurrentQueues[i]; - concurrentQueues[i++] = null; - var queue = concurrentQueues[i]; - concurrentQueues[i++] = null; - var update = concurrentQueues[i]; - concurrentQueues[i++] = null; - var lane = concurrentQueues[i]; - concurrentQueues[i++] = null; - - if (queue !== null && update !== null) { - var pending = queue.pending; + var loggedTypeFailures = {}; + var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; + function setCurrentlyValidatingElement(element) { + { + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV( + element.type, + element._source, + owner ? owner.type : null + ); + ReactDebugCurrentFrame$1.setExtraStackFrame(stack); + } else { + ReactDebugCurrentFrame$1.setExtraStackFrame(null); + } } - - queue.pending = update; } - if (lane !== NoLane) { - markUpdateLaneFromFiberToRoot(fiber, update, lane); - } - } -} -function getConcurrentlyUpdatedLanes() { - return concurrentlyUpdatedLanes; -} + function checkPropTypes( + typeSpecs, + values, + location, + componentName, + element + ) { + { + // $FlowFixMe[incompatible-use] This is okay but Flow doesn't know it. + var has = Function.call.bind(hasOwnProperty); -function enqueueUpdate$1(fiber, queue, update, lane) { - // Don't update the `childLanes` on the return path yet. If we already in - // the middle of rendering, wait until after it has completed. - concurrentQueues[concurrentQueuesIndex++] = fiber; - concurrentQueues[concurrentQueuesIndex++] = queue; - concurrentQueues[concurrentQueuesIndex++] = update; - concurrentQueues[concurrentQueuesIndex++] = lane; - concurrentlyUpdatedLanes = mergeLanes(concurrentlyUpdatedLanes, lane); // The fiber's `lane` field is used in some places to check if any work is - // scheduled, to perform an eager bailout, so we need to update it immediately. - // TODO: We should probably move this to the "shared" queue instead. - - fiber.lanes = mergeLanes(fiber.lanes, lane); - var alternate = fiber.alternate; - - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, lane); - } -} + for (var typeSpecName in typeSpecs) { + if (has(typeSpecs, typeSpecName)) { + var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to + // fail the render phase where it didn't fail before. So we log it. + // After these have been cleaned up, we'll let them throw. -function enqueueConcurrentHookUpdate(fiber, queue, update, lane) { - var concurrentQueue = queue; - var concurrentUpdate = update; - enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); - return getRootForUpdatedFiber(fiber); -} -function enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update) { - // This function is used to queue an update that doesn't need a rerender. The - // only reason we queue it is in case there's a subsequent higher priority - // update that causes it to be rebased. - var lane = NoLane; - var concurrentQueue = queue; - var concurrentUpdate = update; - enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); // Usually we can rely on the upcoming render phase to process the concurrent - // queue. However, since this is a bail out, we're not scheduling any work - // here. So the update we just queued will leak until something else happens - // to schedule work (if ever). - // - // Check if we're currently in the middle of rendering a tree, and if not, - // process the queue immediately to prevent a leak. - - var isConcurrentlyRendering = getWorkInProgressRoot() !== null; - - if (!isConcurrentlyRendering) { - finishQueueingConcurrentUpdates(); - } -} -function enqueueConcurrentClassUpdate(fiber, queue, update, lane) { - var concurrentQueue = queue; - var concurrentUpdate = update; - enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); - return getRootForUpdatedFiber(fiber); -} -function enqueueConcurrentRenderForLane(fiber, lane) { - enqueueUpdate$1(fiber, null, null, lane); - return getRootForUpdatedFiber(fiber); -} // Calling this function outside this module should only be done for backwards -// compatibility and should always be accompanied by a warning. - -function unsafe_markUpdateLaneFromFiberToRoot(sourceFiber, lane) { - // NOTE: For Hyrum's Law reasons, if an infinite update loop is detected, it - // should throw before `markUpdateLaneFromFiberToRoot` is called. But this is - // undefined behavior and we can change it if we need to; it just so happens - // that, at the time of this writing, there's an internal product test that - // happens to rely on this. - var root = getRootForUpdatedFiber(sourceFiber); - markUpdateLaneFromFiberToRoot(sourceFiber, null, lane); - return root; -} + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + if (typeof typeSpecs[typeSpecName] !== "function") { + // eslint-disable-next-line react-internal/prod-error-codes + 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`." + ); + err.name = "Invariant Violation"; + throw err; + } -function markUpdateLaneFromFiberToRoot(sourceFiber, update, lane) { - // Update the source fiber's lanes - sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane); - var alternate = sourceFiber.alternate; + error$1 = typeSpecs[typeSpecName]( + values, + typeSpecName, + componentName, + location, + null, + "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" + ); + } catch (ex) { + error$1 = ex; + } - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, lane); - } // Walk the parent path to the root and update the child lanes. + if (error$1 && !(error$1 instanceof Error)) { + setCurrentlyValidatingElement(element); - var isHidden = false; - var parent = sourceFiber.return; - var node = sourceFiber; + 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 + ); - while (parent !== null) { - parent.childLanes = mergeLanes(parent.childLanes, lane); - alternate = parent.alternate; + setCurrentlyValidatingElement(null); + } - if (alternate !== null) { - alternate.childLanes = mergeLanes(alternate.childLanes, lane); - } + if ( + error$1 instanceof Error && + !(error$1.message in loggedTypeFailures) + ) { + // Only monitor this failure once because there tends to be a lot of the + // same error. + loggedTypeFailures[error$1.message] = true; + setCurrentlyValidatingElement(element); - if (parent.tag === OffscreenComponent) { - // Check if this offscreen boundary is currently hidden. - // - // The instance may be null if the Offscreen parent was unmounted. Usually - // the parent wouldn't be reachable in that case because we disconnect - // fibers from the tree when they are deleted. However, there's a weird - // edge case where setState is called on a fiber that was interrupted - // before it ever mounted. Because it never mounts, it also never gets - // deleted. Because it never gets deleted, its return pointer never gets - // disconnected. Which means it may be attached to a deleted Offscreen - // parent node. (This discovery suggests it may be better for memory usage - // if we don't attach the `return` pointer until the commit phase, though - // in order to do that we'd need some other way to track the return - // pointer during the initial render, like on the stack.) - // - // This case is always accompanied by a warning, but we still need to - // account for it. (There may be other cases that we haven't discovered, - // too.) - var offscreenInstance = parent.stateNode; + error("Failed %s type: %s", location, error$1.message); - if ( - offscreenInstance !== null && - !(offscreenInstance._visibility & OffscreenVisible) - ) { - isHidden = true; + setCurrentlyValidatingElement(null); + } + } + } } } - node = parent; - parent = parent.return; - } - - if (isHidden && update !== null && node.tag === HostRoot) { - var root = node.stateNode; - markHiddenUpdate(root, update, lane); - } -} - -function getRootForUpdatedFiber(sourceFiber) { - // TODO: We will detect and infinite update loop and throw even if this fiber - // has already unmounted. This isn't really necessary but it happens to be the - // current behavior we've used for several release cycles. Consider not - // performing this check if the updated fiber already unmounted, since it's - // not possible for that to cause an infinite update loop. - throwIfInfiniteUpdateLoopDetected(); // When a setState happens, we must ensure the root is scheduled. Because - // update queues do not have a backpointer to the root, the only way to do - // this currently is to walk up the return path. This used to not be a big - // deal because we would have to walk up the return path to set - // the `childLanes`, anyway, but now those two traversals happen at - // different times. - // TODO: Consider adding a `root` backpointer on the update queue. - - detectUpdateOnUnmountedFiber(sourceFiber, sourceFiber); - var node = sourceFiber; - var parent = node.return; - - while (parent !== null) { - detectUpdateOnUnmountedFiber(sourceFiber, node); - node = parent; - parent = node.return; - } - - return node.tag === HostRoot ? node.stateNode : null; -} - -function detectUpdateOnUnmountedFiber(sourceFiber, parent) { - { - var alternate = parent.alternate; + var valueStack = []; + var fiberStack; - if ( - alternate === null && - (parent.flags & (Placement | Hydrating)) !== NoFlags$1 - ) { - warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); + { + fiberStack = []; } - } -} -var UpdateState = 0; -var ReplaceState = 1; -var ForceUpdate = 2; -var CaptureUpdate = 3; // Global state that is reset at the beginning of calling `processUpdateQueue`. -// It should only be read right after calling `processUpdateQueue`, via -// `checkHasForceUpdateAfterProcessing`. + var index = -1; -var hasForceUpdate = false; -var didWarnUpdateInsideUpdate; -var currentlyProcessingQueue; + function createCursor(defaultValue) { + return { + current: defaultValue + }; + } -{ - didWarnUpdateInsideUpdate = false; - currentlyProcessingQueue = null; -} + function pop(cursor, fiber) { + if (index < 0) { + { + error("Unexpected pop."); + } -function initializeUpdateQueue(fiber) { - var queue = { - baseState: fiber.memoizedState, - firstBaseUpdate: null, - lastBaseUpdate: null, - shared: { - pending: null, - lanes: NoLanes, - hiddenCallbacks: null - }, - callbacks: null - }; - fiber.updateQueue = queue; -} -function cloneUpdateQueue(current, workInProgress) { - // Clone the update queue from current. Unless it's already a clone. - var queue = workInProgress.updateQueue; - var currentQueue = current.updateQueue; - - if (queue === currentQueue) { - var clone = { - baseState: currentQueue.baseState, - firstBaseUpdate: currentQueue.firstBaseUpdate, - lastBaseUpdate: currentQueue.lastBaseUpdate, - shared: currentQueue.shared, - callbacks: null - }; - workInProgress.updateQueue = clone; - } -} -function createUpdate(lane) { - var update = { - lane: lane, - tag: UpdateState, - payload: null, - callback: null, - next: null - }; - return update; -} -function enqueueUpdate(fiber, update, lane) { - var updateQueue = fiber.updateQueue; + return; + } - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return null; - } + { + if (fiber !== fiberStack[index]) { + error("Unexpected Fiber popped."); + } + } - var sharedQueue = updateQueue.shared; + cursor.current = valueStack[index]; + valueStack[index] = null; - { - if ( - currentlyProcessingQueue === sharedQueue && - !didWarnUpdateInsideUpdate - ) { - var componentName = getComponentNameFromFiber(fiber); - - 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.\n\nPlease update the following component: %s", - componentName - ); + { + fiberStack[index] = null; + } - didWarnUpdateInsideUpdate = true; + index--; } - } - if (isUnsafeClassRenderPhaseUpdate()) { - // This is an unsafe render phase update. Add directly to the update - // queue so we can process it immediately during the current render. - var pending = sharedQueue.pending; + function push(cursor, value, fiber) { + index++; + valueStack[index] = cursor.current; - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; + { + fiberStack[index] = fiber; + } + + cursor.current = value; } - sharedQueue.pending = update; // Update the childLanes even though we're most likely already rendering - // this fiber. This is for backwards compatibility in the case where you - // update a different component during render phase than the one that is - // currently renderings (a pattern that is accompanied by a warning). + var emptyContextObject = {}; - return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); - } else { - return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); - } -} -function entangleTransitions(root, fiber, lane) { - var updateQueue = fiber.updateQueue; + { + Object.freeze(emptyContextObject); + } // A cursor to the current merged context object on the stack. - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return; - } + function hasContextChanged() { + { + return false; + } + } - var sharedQueue = updateQueue.shared; + function isContextProvider(type) { + { + return false; + } + } - if (isTransitionLane(lane)) { - var queueLanes = sharedQueue.lanes; // If any entangled lanes are no longer pending on the root, then they must - // have finished. We can remove them from the shared queue, which represents - // a superset of the actually pending lanes. In some cases we may entangle - // more than we need to, but that's OK. In fact it's worse if we *don't* - // entangle when we should. + function processChildContext(fiber, type, parentContext) { + { + return parentContext; + } + } - queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. + function findCurrentUnmaskedContext(fiber) { + { + return emptyContextObject; + } + } + + // We use the existence of the state object as an indicator that the component + // is hidden. + var OffscreenVisible = + /* */ + 1; + var OffscreenDetached = + /* */ + 2; + var OffscreenPassiveEffectsConnected = + /* */ + 4; + function isOffscreenManual(offscreenFiber) { + return ( + offscreenFiber.memoizedProps !== null && + offscreenFiber.memoizedProps.mode === "manual" + ); + } - var newQueueLanes = mergeLanes(queueLanes, lane); - sharedQueue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if - // the lane finished since the last time we entangled it. So we need to - // entangle it again, just to be sure. + /** + * inlined Object.is polyfill to avoid requiring consumers ship their own + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is + */ + function is(x, y) { + return ( + (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare + ); + } - markRootEntangled(root, newQueueLanes); - } -} -function enqueueCapturedUpdate(workInProgress, capturedUpdate) { - // Captured updates are updates that are thrown by a child during the render - // phase. They should be discarded if the render is aborted. Therefore, - // we should only put them on the work-in-progress queue, not the current one. - var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone. - - var current = workInProgress.alternate; - - if (current !== null) { - var currentQueue = current.updateQueue; - - if (queue === currentQueue) { - // The work-in-progress queue is the same as current. This happens when - // we bail out on a parent fiber that then captures an error thrown by - // a child. Since we want to append the update only to the work-in - // -progress queue, we need to clone the updates. We usually clone during - // processUpdateQueue, but that didn't happen in this case because we - // skipped over the parent when we bailed out. - var newFirst = null; - var newLast = null; - var firstBaseUpdate = queue.firstBaseUpdate; + var objectIs = typeof Object.is === "function" ? Object.is : is; // $FlowFixMe[method-unbinding] - if (firstBaseUpdate !== null) { - // Loop through the updates and clone them. - var update = firstBaseUpdate; + var nativeConsole = console; + var nativeConsoleLog = null; + var pendingGroupArgs = []; + var printedGroupIndex = -1; - do { - var clone = { - lane: update.lane, - tag: update.tag, - payload: update.payload, - // When this update is rebased, we should not fire its - // callback again. - callback: null, - next: null - }; + function formatLanes(laneOrLanes) { + return "0b" + laneOrLanes.toString(2).padStart(31, "0"); + } - if (newLast === null) { - newFirst = newLast = clone; - } else { - newLast.next = clone; - newLast = clone; - } // $FlowFixMe[incompatible-type] we bail out when we get a null + function group() { + for ( + var _len = arguments.length, groupArgs = new Array(_len), _key = 0; + _key < _len; + _key++ + ) { + groupArgs[_key] = arguments[_key]; + } - update = update.next; - } while (update !== null); // Append the captured update the end of the cloned list. + pendingGroupArgs.push(groupArgs); - if (newLast === null) { - newFirst = newLast = capturedUpdate; - } else { - newLast.next = capturedUpdate; - newLast = capturedUpdate; - } - } else { - // There are no base updates. - newFirst = newLast = capturedUpdate; + if (nativeConsoleLog === null) { + nativeConsoleLog = nativeConsole.log; + nativeConsole.log = log; } - - queue = { - baseState: currentQueue.baseState, - firstBaseUpdate: newFirst, - lastBaseUpdate: newLast, - shared: currentQueue.shared, - callbacks: currentQueue.callbacks - }; - workInProgress.updateQueue = queue; - return; } - } // Append the update to the end of the list. - var lastBaseUpdate = queue.lastBaseUpdate; + function groupEnd() { + pendingGroupArgs.pop(); - if (lastBaseUpdate === null) { - queue.firstBaseUpdate = capturedUpdate; - } else { - lastBaseUpdate.next = capturedUpdate; - } + while (printedGroupIndex >= pendingGroupArgs.length) { + nativeConsole.groupEnd(); + printedGroupIndex--; + } - queue.lastBaseUpdate = capturedUpdate; -} + if (pendingGroupArgs.length === 0) { + nativeConsole.log = nativeConsoleLog; + nativeConsoleLog = null; + } + } -function getStateFromUpdate( - workInProgress, - queue, - update, - prevState, - nextProps, - instance -) { - switch (update.tag) { - case ReplaceState: { - var payload = update.payload; - - if (typeof payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); + function log() { + if (printedGroupIndex < pendingGroupArgs.length - 1) { + for (var i = printedGroupIndex + 1; i < pendingGroupArgs.length; i++) { + var groupArgs = pendingGroupArgs[i]; + nativeConsole.group.apply(nativeConsole, groupArgs); } - var nextState = payload.call(instance, prevState, nextProps); - - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + printedGroupIndex = pendingGroupArgs.length - 1; + } - try { - payload.call(instance, prevState, nextProps); - } finally { - setIsStrictModeForDevtools(false); - } - } + if (typeof nativeConsoleLog === "function") { + nativeConsoleLog.apply(void 0, arguments); + } else { + nativeConsole.log.apply(nativeConsole, arguments); + } + } - exitDisallowedContextReadInDEV(); + var REACT_LOGO_STYLE = + "background-color: #20232a; color: #61dafb; padding: 0 2px;"; + function logCommitStarted(lanes) { + { + if (enableDebugTracing) { + group( + "%c\u269B\uFE0F%c commit%c (" + formatLanes(lanes) + ")", + REACT_LOGO_STYLE, + "", + "font-weight: normal;" + ); } - - return nextState; - } // State object - - return payload; + } } - - case CaptureUpdate: { - workInProgress.flags = - (workInProgress.flags & ~ShouldCapture) | DidCapture; + function logCommitStopped() { + { + if (enableDebugTracing) { + groupEnd(); + } + } } - // Intentional fallthrough + var PossiblyWeakMap$1 = typeof WeakMap === "function" ? WeakMap : Map; // $FlowFixMe[incompatible-type]: Flow cannot handle polymorphic WeakMaps - case UpdateState: { - var _payload = update.payload; - var partialState; - - if (typeof _payload === "function") { - // Updater function - { - enterDisallowedContextReadInDEV(); - } + var wakeableIDs = new PossiblyWeakMap$1(); + var wakeableID = 0; - partialState = _payload.call(instance, prevState, nextProps); + function getWakeableID(wakeable) { + if (!wakeableIDs.has(wakeable)) { + wakeableIDs.set(wakeable, wakeableID++); + } - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + return wakeableIDs.get(wakeable); + } - try { - _payload.call(instance, prevState, nextProps); - } finally { - setIsStrictModeForDevtools(false); + function logComponentSuspended(componentName, wakeable) { + { + if (enableDebugTracing) { + var id = getWakeableID(wakeable); + var display = wakeable.displayName || wakeable; + log( + "%c\u269B\uFE0F%c " + componentName + " suspended", + REACT_LOGO_STYLE, + "color: #80366d; font-weight: bold;", + id, + display + ); + wakeable.then( + function () { + log( + "%c\u269B\uFE0F%c " + componentName + " resolved", + REACT_LOGO_STYLE, + "color: #80366d; font-weight: bold;", + id, + display + ); + }, + function () { + log( + "%c\u269B\uFE0F%c " + componentName + " rejected", + REACT_LOGO_STYLE, + "color: #80366d; font-weight: bold;", + id, + display + ); } - } - - exitDisallowedContextReadInDEV(); + ); + } + } + } + function logLayoutEffectsStarted(lanes) { + { + if (enableDebugTracing) { + group( + "%c\u269B\uFE0F%c layout effects%c (" + formatLanes(lanes) + ")", + REACT_LOGO_STYLE, + "", + "font-weight: normal;" + ); + } + } + } + function logLayoutEffectsStopped() { + { + if (enableDebugTracing) { + groupEnd(); + } + } + } + function logPassiveEffectsStarted(lanes) { + { + if (enableDebugTracing) { + group( + "%c\u269B\uFE0F%c passive effects%c (" + formatLanes(lanes) + ")", + REACT_LOGO_STYLE, + "", + "font-weight: normal;" + ); + } + } + } + function logPassiveEffectsStopped() { + { + if (enableDebugTracing) { + groupEnd(); + } + } + } + function logRenderStarted(lanes) { + { + if (enableDebugTracing) { + group( + "%c\u269B\uFE0F%c render%c (" + formatLanes(lanes) + ")", + REACT_LOGO_STYLE, + "", + "font-weight: normal;" + ); + } + } + } + function logRenderStopped() { + { + if (enableDebugTracing) { + groupEnd(); + } + } + } + function logForceUpdateScheduled(componentName, lane) { + { + if (enableDebugTracing) { + log( + "%c\u269B\uFE0F%c " + + componentName + + " forced update %c(" + + formatLanes(lane) + + ")", + REACT_LOGO_STYLE, + "color: #db2e1f; font-weight: bold;", + "" + ); + } + } + } + function logStateUpdateScheduled(componentName, lane, payloadOrAction) { + { + if (enableDebugTracing) { + log( + "%c\u269B\uFE0F%c " + + componentName + + " updated state %c(" + + formatLanes(lane) + + ")", + REACT_LOGO_STYLE, + "color: #01a252; font-weight: bold;", + "", + payloadOrAction + ); } - } else { - // Partial state object - partialState = _payload; } - - if (partialState === null || partialState === undefined) { - // Null and undefined are treated as no-ops. - return prevState; - } // Merge the partial state and the previous state. - - return assign({}, prevState, partialState); } - case ForceUpdate: { - hasForceUpdate = true; - return prevState; + // This is imported by the event replaying implementation in React DOM. It's + // in a separate file to break a circular dependency between the renderer and + // the reconciler. + function isRootDehydrated(root) { + var currentState = root.current.memoizedState; + return currentState.isDehydrated; } - } - return prevState; -} + var contextStackCursor = createCursor(null); + var contextFiberStackCursor = createCursor(null); + var rootInstanceStackCursor = createCursor(null); // Represents the nearest host transition provider (in React DOM, a ) -function processUpdateQueue(workInProgress, props, instance, renderLanes) { - // This is always non-null on a ClassComponent or HostRoot - var queue = workInProgress.updateQueue; - hasForceUpdate = false; + function requiredContext(c) { + { + if (c === null) { + error( + "Expected host context to exist. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + } + } - { - currentlyProcessingQueue = queue.shared; - } + return c; + } - var firstBaseUpdate = queue.firstBaseUpdate; - var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. + function getRootHostContainer() { + var rootInstance = requiredContext(rootInstanceStackCursor.current); + return rootInstance; + } - var pendingQueue = queue.shared.pending; + function pushHostContainer(fiber, nextRootInstance) { + // Push current root instance onto the stack; + // This allows us to reset root when portals are popped. + push(rootInstanceStackCursor, nextRootInstance, fiber); // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. - if (pendingQueue !== null) { - queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first - // and last so that it's non-circular. + push(contextFiberStackCursor, fiber, fiber); // Finally, we need to push the host context to the stack. + // However, we can't just call getRootHostContext() and push it because + // we'd have a different number of entries on the stack depending on + // whether getRootHostContext() throws somewhere in renderer code or not. + // So we push an empty value first. This lets us safely unwind on errors. - var lastPendingUpdate = pendingQueue; - var firstPendingUpdate = lastPendingUpdate.next; - lastPendingUpdate.next = null; // Append pending updates to base queue + push(contextStackCursor, null, fiber); + var nextRootContext = getRootHostContext(); // Now that we know this function doesn't throw, replace it. - if (lastBaseUpdate === null) { - firstBaseUpdate = firstPendingUpdate; - } else { - lastBaseUpdate.next = firstPendingUpdate; + pop(contextStackCursor, fiber); + push(contextStackCursor, nextRootContext, fiber); } - lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then - // we need to transfer the updates to that queue, too. Because the base - // queue is a singly-linked list with no cycles, we can append to both - // lists and take advantage of structural sharing. - // TODO: Pass `current` as argument - - var current = workInProgress.alternate; + function popHostContainer(fiber) { + pop(contextStackCursor, fiber); + pop(contextFiberStackCursor, fiber); + pop(rootInstanceStackCursor, fiber); + } - if (current !== null) { - // This is always non-null on a ClassComponent or HostRoot - var currentQueue = current.updateQueue; - var currentLastBaseUpdate = currentQueue.lastBaseUpdate; + function getHostContext() { + var context = requiredContext(contextStackCursor.current); + return context; + } - if (currentLastBaseUpdate !== lastBaseUpdate) { - if (currentLastBaseUpdate === null) { - currentQueue.firstBaseUpdate = firstPendingUpdate; - } else { - currentLastBaseUpdate.next = firstPendingUpdate; - } + function pushHostContext(fiber) { + var context = requiredContext(contextStackCursor.current); + var nextContext = getChildHostContext(); // Don't push this Fiber's context unless it's unique. - currentQueue.lastBaseUpdate = lastPendingUpdate; + if (context !== nextContext) { + // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. + push(contextFiberStackCursor, fiber, fiber); + push(contextStackCursor, nextContext, fiber); } } - } // These values may change as we process the queue. - - if (firstBaseUpdate !== null) { - // Iterate through the list of updates to compute the result. - var newState = queue.baseState; // TODO: Don't need to accumulate this. Instead, we can remove renderLanes - // from the original lanes. - var newLanes = NoLanes; - var newBaseState = null; - var newFirstBaseUpdate = null; - var newLastBaseUpdate = null; - var update = firstBaseUpdate; + function popHostContext(fiber) { + if (contextFiberStackCursor.current === fiber) { + // Do not pop unless this Fiber provided the current context. + // pushHostContext() only pushes Fibers that provide unique contexts. + pop(contextStackCursor, fiber); + pop(contextFiberStackCursor, fiber); + } + } - do { - // An extra OffscreenLane bit is added to updates that were made to - // a hidden tree, so that we can distinguish them from updates that were - // already there when the tree was hidden. - var updateLane = removeLanes(update.lane, OffscreenLane); - var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then - // it's not a "base" update and we should disregard the extra base lanes - // that were added to renderLanes when we entered the Offscreen tree. + var isHydrating = false; // This flag allows for warning supression when we expect there to be mismatches + // due to earlier mismatches or a suspended fiber. - var shouldSkipUpdate = isHiddenUpdate - ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) - : !isSubsetOfLanes(renderLanes, updateLane); + var didSuspendOrErrorDEV = false; // Hydration errors that were thrown inside this boundary - if (shouldSkipUpdate) { - // Priority is insufficient. Skip this update. If this is the first - // skipped update, the previous update/state is the new base - // update/state. - var clone = { - lane: updateLane, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }; + var hydrationErrors = null; + function didSuspendOrErrorWhileHydratingDEV() { + { + return didSuspendOrErrorDEV; + } + } - if (newLastBaseUpdate === null) { - newFirstBaseUpdate = newLastBaseUpdate = clone; - newBaseState = newState; - } else { - newLastBaseUpdate = newLastBaseUpdate.next = clone; - } // Update the remaining priority in the queue. + function prepareToHydrateHostInstance(fiber, hostContext) { + { + throw new Error( + "Expected prepareToHydrateHostInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } + } - newLanes = mergeLanes(newLanes, updateLane); - } else { - // This update does have sufficient priority. - if (newLastBaseUpdate !== null) { - var _clone = { - // This update is going to be committed so we never want uncommit - // it. Using NoLane works because 0 is a subset of all bitmasks, so - // this will never be skipped by the check above. - lane: NoLane, - tag: update.tag, - payload: update.payload, - // When this update is rebased, we should not fire its - // callback again. - callback: null, - next: null - }; - newLastBaseUpdate = newLastBaseUpdate.next = _clone; - } // Process this update. + function prepareToHydrateHostTextInstance(fiber) { + { + throw new Error( + "Expected prepareToHydrateHostTextInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } + } - newState = getStateFromUpdate( - workInProgress, - queue, - update, - newState, - props, - instance + function prepareToHydrateHostSuspenseInstance(fiber) { + { + throw new Error( + "Expected prepareToHydrateHostSuspenseInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." ); - var callback = update.callback; + } + } - if (callback !== null) { - workInProgress.flags |= Callback; + function popHydrationState(fiber) { + { + return false; + } + } - if (isHiddenUpdate) { - workInProgress.flags |= Visibility; - } + function upgradeHydrationErrorsToRecoverable() { + if (hydrationErrors !== null) { + // Successfully completed a forced client render. The errors that occurred + // during the hydration attempt are now recovered. We will log them in + // commit phase, once the entire tree has finished. + queueRecoverableErrors(hydrationErrors); + hydrationErrors = null; + } + } - var callbacks = queue.callbacks; + function getIsHydrating() { + return isHydrating; + } - if (callbacks === null) { - queue.callbacks = [callback]; + function queueHydrationError(error) { + if (hydrationErrors === null) { + hydrationErrors = [error]; + } else { + hydrationErrors.push(error); + } + } + + // we wait until the current render is over (either finished or interrupted) + // before adding it to the fiber/hook queue. Push to this array so we can + // access the queue, fiber, update, et al later. + + var concurrentQueues = []; + var concurrentQueuesIndex = 0; + var concurrentlyUpdatedLanes = NoLanes; + function finishQueueingConcurrentUpdates() { + var endIndex = concurrentQueuesIndex; + concurrentQueuesIndex = 0; + concurrentlyUpdatedLanes = NoLanes; + var i = 0; + + while (i < endIndex) { + var fiber = concurrentQueues[i]; + concurrentQueues[i++] = null; + var queue = concurrentQueues[i]; + concurrentQueues[i++] = null; + var update = concurrentQueues[i]; + concurrentQueues[i++] = null; + var lane = concurrentQueues[i]; + concurrentQueues[i++] = null; + + if (queue !== null && update !== null) { + var pending = queue.pending; + + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; } else { - callbacks.push(callback); + update.next = pending.next; + pending.next = update; } - } - } // $FlowFixMe[incompatible-type] we bail out when we get a null - update = update.next; + queue.pending = update; + } - if (update === null) { - pendingQueue = queue.shared.pending; + if (lane !== NoLane) { + markUpdateLaneFromFiberToRoot(fiber, update, lane); + } + } + } + function getConcurrentlyUpdatedLanes() { + return concurrentlyUpdatedLanes; + } - if (pendingQueue === null) { - break; - } else { - // An update was scheduled from inside a reducer. Add the new - // pending updates to the end of the list and keep processing. - var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we - // unravel them when transferring them to the base queue. - - var _firstPendingUpdate = _lastPendingUpdate.next; - _lastPendingUpdate.next = null; - update = _firstPendingUpdate; - queue.lastBaseUpdate = _lastPendingUpdate; - queue.shared.pending = null; - } - } - } while (true); - - if (newLastBaseUpdate === null) { - newBaseState = newState; - } - - queue.baseState = newBaseState; - queue.firstBaseUpdate = newFirstBaseUpdate; - queue.lastBaseUpdate = newLastBaseUpdate; - - if (firstBaseUpdate === null) { - // `queue.lanes` is used for entangling transitions. We can set it back to - // zero once the queue is empty. - queue.shared.lanes = NoLanes; - } // Set the remaining expiration time to be whatever is remaining in the queue. - // This should be fine because the only two other things that contribute to - // expiration time are props and context. We're already in the middle of the - // begin phase by the time we start processing the queue, so we've already - // dealt with the props. Context in components that specify - // shouldComponentUpdate is tricky; but we'll have to account for - // that regardless. - - markSkippedUpdateLanes(newLanes); - workInProgress.lanes = newLanes; - workInProgress.memoizedState = newState; - } - - { - currentlyProcessingQueue = null; - } -} + function enqueueUpdate$1(fiber, queue, update, lane) { + // Don't update the `childLanes` on the return path yet. If we already in + // the middle of rendering, wait until after it has completed. + concurrentQueues[concurrentQueuesIndex++] = fiber; + concurrentQueues[concurrentQueuesIndex++] = queue; + concurrentQueues[concurrentQueuesIndex++] = update; + concurrentQueues[concurrentQueuesIndex++] = lane; + concurrentlyUpdatedLanes = mergeLanes(concurrentlyUpdatedLanes, lane); // The fiber's `lane` field is used in some places to check if any work is + // scheduled, to perform an eager bailout, so we need to update it immediately. + // TODO: We should probably move this to the "shared" queue instead. -function callCallback(callback, context) { - if (typeof callback !== "function") { - throw new Error( - "Invalid argument passed as callback. Expected a function. Instead " + - ("received: " + callback) - ); - } + fiber.lanes = mergeLanes(fiber.lanes, lane); + var alternate = fiber.alternate; - callback.call(context); -} + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, lane); + } + } -function resetHasForceUpdateBeforeProcessing() { - hasForceUpdate = false; -} -function checkHasForceUpdateAfterProcessing() { - return hasForceUpdate; -} -function deferHiddenCallbacks(updateQueue) { - // When an update finishes on a hidden component, its callback should not - // be fired until/unless the component is made visible again. Stash the - // callback on the shared queue object so it can be fired later. - var newHiddenCallbacks = updateQueue.callbacks; + function enqueueConcurrentHookUpdate(fiber, queue, update, lane) { + var concurrentQueue = queue; + var concurrentUpdate = update; + enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); + return getRootForUpdatedFiber(fiber); + } + function enqueueConcurrentHookUpdateAndEagerlyBailout( + fiber, + queue, + update + ) { + // This function is used to queue an update that doesn't need a rerender. The + // only reason we queue it is in case there's a subsequent higher priority + // update that causes it to be rebased. + var lane = NoLane; + var concurrentQueue = queue; + var concurrentUpdate = update; + enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); // Usually we can rely on the upcoming render phase to process the concurrent + // queue. However, since this is a bail out, we're not scheduling any work + // here. So the update we just queued will leak until something else happens + // to schedule work (if ever). + // + // Check if we're currently in the middle of rendering a tree, and if not, + // process the queue immediately to prevent a leak. - if (newHiddenCallbacks !== null) { - var existingHiddenCallbacks = updateQueue.shared.hiddenCallbacks; + var isConcurrentlyRendering = getWorkInProgressRoot() !== null; - if (existingHiddenCallbacks === null) { - updateQueue.shared.hiddenCallbacks = newHiddenCallbacks; - } else { - updateQueue.shared.hiddenCallbacks = - existingHiddenCallbacks.concat(newHiddenCallbacks); + if (!isConcurrentlyRendering) { + finishQueueingConcurrentUpdates(); + } } - } -} -function commitHiddenCallbacks(updateQueue, context) { - // This component is switching from hidden -> visible. Commit any callbacks - // that were previously deferred. - var hiddenCallbacks = updateQueue.shared.hiddenCallbacks; - - if (hiddenCallbacks !== null) { - updateQueue.shared.hiddenCallbacks = null; + function enqueueConcurrentClassUpdate(fiber, queue, update, lane) { + var concurrentQueue = queue; + var concurrentUpdate = update; + enqueueUpdate$1(fiber, concurrentQueue, concurrentUpdate, lane); + return getRootForUpdatedFiber(fiber); + } + function enqueueConcurrentRenderForLane(fiber, lane) { + enqueueUpdate$1(fiber, null, null, lane); + return getRootForUpdatedFiber(fiber); + } // Calling this function outside this module should only be done for backwards + // compatibility and should always be accompanied by a warning. - for (var i = 0; i < hiddenCallbacks.length; i++) { - var callback = hiddenCallbacks[i]; - callCallback(callback, context); + function unsafe_markUpdateLaneFromFiberToRoot(sourceFiber, lane) { + // NOTE: For Hyrum's Law reasons, if an infinite update loop is detected, it + // should throw before `markUpdateLaneFromFiberToRoot` is called. But this is + // undefined behavior and we can change it if we need to; it just so happens + // that, at the time of this writing, there's an internal product test that + // happens to rely on this. + var root = getRootForUpdatedFiber(sourceFiber); + markUpdateLaneFromFiberToRoot(sourceFiber, null, lane); + return root; } - } -} -function commitCallbacks(updateQueue, context) { - var callbacks = updateQueue.callbacks; - if (callbacks !== null) { - updateQueue.callbacks = null; + function markUpdateLaneFromFiberToRoot(sourceFiber, update, lane) { + // Update the source fiber's lanes + sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane); + var alternate = sourceFiber.alternate; - for (var i = 0; i < callbacks.length; i++) { - var callback = callbacks[i]; - callCallback(callback, context); - } - } -} + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, lane); + } // Walk the parent path to the root and update the child lanes. -/** - * Performs equality by iterating through keys on an object and returning false - * when any key has values which are not strictly equal between the arguments. - * Returns true when the values of all keys are strictly equal. - */ + var isHidden = false; + var parent = sourceFiber.return; + var node = sourceFiber; -function shallowEqual(objA, objB) { - if (objectIs(objA, objB)) { - return true; - } + while (parent !== null) { + parent.childLanes = mergeLanes(parent.childLanes, lane); + alternate = parent.alternate; - if ( - typeof objA !== "object" || - objA === null || - typeof objB !== "object" || - objB === null - ) { - return false; - } + if (alternate !== null) { + alternate.childLanes = mergeLanes(alternate.childLanes, lane); + } - var keysA = Object.keys(objA); - var keysB = Object.keys(objB); + if (parent.tag === OffscreenComponent) { + // Check if this offscreen boundary is currently hidden. + // + // The instance may be null if the Offscreen parent was unmounted. Usually + // the parent wouldn't be reachable in that case because we disconnect + // fibers from the tree when they are deleted. However, there's a weird + // edge case where setState is called on a fiber that was interrupted + // before it ever mounted. Because it never mounts, it also never gets + // deleted. Because it never gets deleted, its return pointer never gets + // disconnected. Which means it may be attached to a deleted Offscreen + // parent node. (This discovery suggests it may be better for memory usage + // if we don't attach the `return` pointer until the commit phase, though + // in order to do that we'd need some other way to track the return + // pointer during the initial render, like on the stack.) + // + // This case is always accompanied by a warning, but we still need to + // account for it. (There may be other cases that we haven't discovered, + // too.) + var offscreenInstance = parent.stateNode; - if (keysA.length !== keysB.length) { - return false; - } // Test for A's keys different from B. + if ( + offscreenInstance !== null && + !(offscreenInstance._visibility & OffscreenVisible) + ) { + isHidden = true; + } + } - for (var i = 0; i < keysA.length; i++) { - var currentKey = keysA[i]; + node = parent; + parent = parent.return; + } - if ( - !hasOwnProperty.call(objB, currentKey) || // $FlowFixMe[incompatible-use] lost refinement of `objB` - !objectIs(objA[currentKey], objB[currentKey]) - ) { - return false; + if (isHidden && update !== null && node.tag === HostRoot) { + var root = node.stateNode; + markHiddenUpdate(root, update, lane); + } } - } - return true; -} + function getRootForUpdatedFiber(sourceFiber) { + // TODO: We will detect and infinite update loop and throw even if this fiber + // has already unmounted. This isn't really necessary but it happens to be the + // current behavior we've used for several release cycles. Consider not + // performing this check if the updated fiber already unmounted, since it's + // not possible for that to cause an infinite update loop. + throwIfInfiniteUpdateLoopDetected(); // When a setState happens, we must ensure the root is scheduled. Because + // update queues do not have a backpointer to the root, the only way to do + // this currently is to walk up the return path. This used to not be a big + // deal because we would have to walk up the return path to set + // the `childLanes`, anyway, but now those two traversals happen at + // different times. + // TODO: Consider adding a `root` backpointer on the update queue. -function describeFiber(fiber) { - switch (fiber.tag) { - case HostHoistable: - case HostSingleton: - case HostComponent: - return describeBuiltInComponentFrame(fiber.type); + detectUpdateOnUnmountedFiber(sourceFiber, sourceFiber); + var node = sourceFiber; + var parent = node.return; - case LazyComponent: - return describeBuiltInComponentFrame("Lazy"); + while (parent !== null) { + detectUpdateOnUnmountedFiber(sourceFiber, node); + node = parent; + parent = node.return; + } + + return node.tag === HostRoot ? node.stateNode : null; + } - case SuspenseComponent: - return describeBuiltInComponentFrame("Suspense"); + function detectUpdateOnUnmountedFiber(sourceFiber, parent) { + { + var alternate = parent.alternate; - case SuspenseListComponent: - return describeBuiltInComponentFrame("SuspenseList"); + if ( + alternate === null && + (parent.flags & (Placement | Hydrating)) !== NoFlags$1 + ) { + warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); + } + } + } - case FunctionComponent: - case IndeterminateComponent: - case SimpleMemoComponent: - return describeFunctionComponentFrame(fiber.type); + var UpdateState = 0; + var ReplaceState = 1; + var ForceUpdate = 2; + var CaptureUpdate = 3; // Global state that is reset at the beginning of calling `processUpdateQueue`. + // It should only be read right after calling `processUpdateQueue`, via + // `checkHasForceUpdateAfterProcessing`. - case ForwardRef: - return describeFunctionComponentFrame(fiber.type.render); + var hasForceUpdate = false; + var didWarnUpdateInsideUpdate; + var currentlyProcessingQueue; - case ClassComponent: - return describeClassComponentFrame(fiber.type); + { + didWarnUpdateInsideUpdate = false; + currentlyProcessingQueue = null; + } + + function initializeUpdateQueue(fiber) { + var queue = { + baseState: fiber.memoizedState, + firstBaseUpdate: null, + lastBaseUpdate: null, + shared: { + pending: null, + lanes: NoLanes, + hiddenCallbacks: null + }, + callbacks: null + }; + fiber.updateQueue = queue; + } + function cloneUpdateQueue(current, workInProgress) { + // Clone the update queue from current. Unless it's already a clone. + var queue = workInProgress.updateQueue; + var currentQueue = current.updateQueue; - default: - return ""; - } -} + if (queue === currentQueue) { + var clone = { + baseState: currentQueue.baseState, + firstBaseUpdate: currentQueue.firstBaseUpdate, + lastBaseUpdate: currentQueue.lastBaseUpdate, + shared: currentQueue.shared, + callbacks: null + }; + workInProgress.updateQueue = clone; + } + } + function createUpdate(lane) { + var update = { + lane: lane, + tag: UpdateState, + payload: null, + callback: null, + next: null + }; + return update; + } + function enqueueUpdate(fiber, update, lane) { + var updateQueue = fiber.updateQueue; -function getStackByFiberInDevAndProd(workInProgress) { - try { - var info = ""; - var node = workInProgress; + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return null; + } - do { - info += describeFiber(node); // $FlowFixMe[incompatible-type] we bail out when we get a null + var sharedQueue = updateQueue.shared; - node = node.return; - } while (node); + { + if ( + currentlyProcessingQueue === sharedQueue && + !didWarnUpdateInsideUpdate + ) { + var componentName = getComponentNameFromFiber(fiber); - return info; - } catch (x) { - return "\nError generating stack: " + x.message + "\n" + x.stack; - } -} + 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.\n\nPlease update the following component: %s", + componentName + ); -var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; -var current = null; -var isRendering = false; -function getCurrentFiberOwnerNameInDevOrNull() { - { - if (current === null) { - return null; - } + didWarnUpdateInsideUpdate = true; + } + } - var owner = current._debugOwner; + if (isUnsafeClassRenderPhaseUpdate()) { + // This is an unsafe render phase update. Add directly to the update + // queue so we can process it immediately during the current render. + var pending = sharedQueue.pending; - if (owner !== null && typeof owner !== "undefined") { - return getComponentNameFromFiber(owner); - } - } + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; + } - return null; -} + sharedQueue.pending = update; // Update the childLanes even though we're most likely already rendering + // this fiber. This is for backwards compatibility in the case where you + // update a different component during render phase than the one that is + // currently renderings (a pattern that is accompanied by a warning). -function getCurrentFiberStackInDev() { - { - if (current === null) { - return ""; - } // Safe because if current fiber exists, we are reconciling, - // and it is guaranteed to be the work-in-progress version. + return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); + } else { + return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); + } + } + function entangleTransitions(root, fiber, lane) { + var updateQueue = fiber.updateQueue; - return getStackByFiberInDevAndProd(current); - } -} + if (updateQueue === null) { + // Only occurs if the fiber has been unmounted. + return; + } -function resetCurrentFiber() { - { - ReactDebugCurrentFrame.getCurrentStack = null; - current = null; - isRendering = false; - } -} -function setCurrentFiber(fiber) { - { - ReactDebugCurrentFrame.getCurrentStack = - fiber === null ? null : getCurrentFiberStackInDev; - current = fiber; - isRendering = false; - } -} -function getCurrentFiber() { - { - return current; - } -} -function setIsRendering(rendering) { - { - isRendering = rendering; - } -} + var sharedQueue = updateQueue.shared; -var ReactStrictModeWarnings = { - recordUnsafeLifecycleWarnings: function (fiber, instance) {}, - flushPendingUnsafeLifecycleWarnings: function () {}, - recordLegacyContextWarning: function (fiber, instance) {}, - flushLegacyContextWarning: function () {}, - discardPendingWarnings: function () {} -}; + if (isTransitionLane(lane)) { + var queueLanes = sharedQueue.lanes; // If any entangled lanes are no longer pending on the root, then they must + // have finished. We can remove them from the shared queue, which represents + // a superset of the actually pending lanes. In some cases we may entangle + // more than we need to, but that's OK. In fact it's worse if we *don't* + // entangle when we should. -{ - var findStrictRoot = function (fiber) { - var maybeStrictRoot = null; - var node = fiber; + queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. - while (node !== null) { - if (node.mode & StrictLegacyMode) { - maybeStrictRoot = node; - } + var newQueueLanes = mergeLanes(queueLanes, lane); + sharedQueue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if + // the lane finished since the last time we entangled it. So we need to + // entangle it again, just to be sure. - node = node.return; + markRootEntangled(root, newQueueLanes); + } } + function enqueueCapturedUpdate(workInProgress, capturedUpdate) { + // Captured updates are updates that are thrown by a child during the render + // phase. They should be discarded if the render is aborted. Therefore, + // we should only put them on the work-in-progress queue, not the current one. + var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone. - return maybeStrictRoot; - }; + var current = workInProgress.alternate; - var setToSortedString = function (set) { - var array = []; - set.forEach(function (value) { - array.push(value); - }); - return array.sort().join(", "); - }; + if (current !== null) { + var currentQueue = current.updateQueue; + + if (queue === currentQueue) { + // The work-in-progress queue is the same as current. This happens when + // we bail out on a parent fiber that then captures an error thrown by + // a child. Since we want to append the update only to the work-in + // -progress queue, we need to clone the updates. We usually clone during + // processUpdateQueue, but that didn't happen in this case because we + // skipped over the parent when we bailed out. + var newFirst = null; + var newLast = null; + var firstBaseUpdate = queue.firstBaseUpdate; + + if (firstBaseUpdate !== null) { + // Loop through the updates and clone them. + var update = firstBaseUpdate; - var pendingComponentWillMountWarnings = []; - var pendingUNSAFE_ComponentWillMountWarnings = []; - var pendingComponentWillReceivePropsWarnings = []; - var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - var pendingComponentWillUpdateWarnings = []; - var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. + do { + var clone = { + lane: update.lane, + tag: update.tag, + payload: update.payload, + // When this update is rebased, we should not fire its + // callback again. + callback: null, + next: null + }; + + if (newLast === null) { + newFirst = newLast = clone; + } else { + newLast.next = clone; + newLast = clone; + } // $FlowFixMe[incompatible-type] we bail out when we get a null - var didWarnAboutUnsafeLifecycles = new Set(); + update = update.next; + } while (update !== null); // Append the captured update the end of the cloned list. - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function ( - fiber, - instance - ) { - // Dedupe strategy: Warn once per component. - if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { - return; - } + if (newLast === null) { + newFirst = newLast = capturedUpdate; + } else { + newLast.next = capturedUpdate; + newLast = capturedUpdate; + } + } else { + // There are no base updates. + newFirst = newLast = capturedUpdate; + } - if ( - typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - pendingComponentWillMountWarnings.push(fiber); - } + queue = { + baseState: currentQueue.baseState, + firstBaseUpdate: newFirst, + lastBaseUpdate: newLast, + shared: currentQueue.shared, + callbacks: currentQueue.callbacks + }; + workInProgress.updateQueue = queue; + return; + } + } // Append the update to the end of the list. - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillMount === "function" - ) { - pendingUNSAFE_ComponentWillMountWarnings.push(fiber); - } + var lastBaseUpdate = queue.lastBaseUpdate; - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== true - ) { - pendingComponentWillReceivePropsWarnings.push(fiber); - } + if (lastBaseUpdate === null) { + queue.firstBaseUpdate = capturedUpdate; + } else { + lastBaseUpdate.next = capturedUpdate; + } - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); + queue.lastBaseUpdate = capturedUpdate; } - if ( - typeof instance.componentWillUpdate === "function" && - instance.componentWillUpdate.__suppressDeprecationWarning !== true + function getStateFromUpdate( + workInProgress, + queue, + update, + prevState, + nextProps, + instance ) { - pendingComponentWillUpdateWarnings.push(fiber); - } + switch (update.tag) { + case ReplaceState: { + var payload = update.payload; - if ( - fiber.mode & StrictLegacyMode && - typeof instance.UNSAFE_componentWillUpdate === "function" - ) { - pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); - } - }; - - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function () { - // We do an initial pass to gather component names - var componentWillMountUniqueNames = new Set(); + if (typeof payload === "function") { + // Updater function + { + enterDisallowedContextReadInDEV(); + } - if (pendingComponentWillMountWarnings.length > 0) { - pendingComponentWillMountWarnings.forEach(function (fiber) { - componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillMountWarnings = []; - } + var nextState = payload.call(instance, prevState, nextProps); - var UNSAFE_componentWillMountUniqueNames = new Set(); + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); - if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { - pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) { - UNSAFE_componentWillMountUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillMountWarnings = []; - } + try { + payload.call(instance, prevState, nextProps); + } finally { + setIsStrictModeForDevtools(false); + } + } - var componentWillReceivePropsUniqueNames = new Set(); + exitDisallowedContextReadInDEV(); + } - if (pendingComponentWillReceivePropsWarnings.length > 0) { - pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { - componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillReceivePropsWarnings = []; - } + return nextState; + } // State object - var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); + return payload; + } - if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(function (fiber) { - UNSAFE_componentWillReceivePropsUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - } + case CaptureUpdate: { + workInProgress.flags = + (workInProgress.flags & ~ShouldCapture) | DidCapture; + } + // Intentional fallthrough - var componentWillUpdateUniqueNames = new Set(); + case UpdateState: { + var _payload = update.payload; + var partialState; - if (pendingComponentWillUpdateWarnings.length > 0) { - pendingComponentWillUpdateWarnings.forEach(function (fiber) { - componentWillUpdateUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillUpdateWarnings = []; - } + if (typeof _payload === "function") { + // Updater function + { + enterDisallowedContextReadInDEV(); + } - var UNSAFE_componentWillUpdateUniqueNames = new Set(); + partialState = _payload.call(instance, prevState, nextProps); - if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { - pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function (fiber) { - UNSAFE_componentWillUpdateUniqueNames.add( - getComponentNameFromFiber(fiber) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillUpdateWarnings = []; - } // Finally, we flush all the warnings - // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' - - if (UNSAFE_componentWillMountUniqueNames.size > 0) { - var sortedNames = setToSortedString(UNSAFE_componentWillMountUniqueNames); - - 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 - ); - } + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); - if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames = setToSortedString( - UNSAFE_componentWillReceivePropsUniqueNames - ); + try { + _payload.call(instance, prevState, nextProps); + } finally { + setIsStrictModeForDevtools(false); + } + } - 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 - ); - } + exitDisallowedContextReadInDEV(); + } + } else { + // Partial state object + partialState = _payload; + } - if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { - var _sortedNames2 = setToSortedString( - UNSAFE_componentWillUpdateUniqueNames - ); + if (partialState === null || partialState === undefined) { + // Null and undefined are treated as no-ops. + return prevState; + } // Merge the partial state and the previous state. - 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 - ); - } + return assign({}, prevState, partialState); + } - if (componentWillMountUniqueNames.size > 0) { - var _sortedNames3 = setToSortedString(componentWillMountUniqueNames); + case ForceUpdate: { + hasForceUpdate = true; + return prevState; + } + } - 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 - ); + return prevState; } - if (componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames4 = setToSortedString( - componentWillReceivePropsUniqueNames - ); - - 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 - ); - } + function processUpdateQueue(workInProgress, props, instance, renderLanes) { + // This is always non-null on a ClassComponent or HostRoot + var queue = workInProgress.updateQueue; + hasForceUpdate = false; - if (componentWillUpdateUniqueNames.size > 0) { - var _sortedNames5 = setToSortedString(componentWillUpdateUniqueNames); + { + currentlyProcessingQueue = queue.shared; + } - 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 - ); - } - }; + var firstBaseUpdate = queue.firstBaseUpdate; + var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. - var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. + var pendingQueue = queue.shared.pending; - var didWarnAboutLegacyContext = new Set(); + if (pendingQueue !== null) { + queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first + // and last so that it's non-circular. - ReactStrictModeWarnings.recordLegacyContextWarning = function ( - fiber, - instance - ) { - var strictRoot = findStrictRoot(fiber); + var lastPendingUpdate = pendingQueue; + var firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = null; // Append pending updates to base queue - if (strictRoot === null) { - 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." - ); + if (lastBaseUpdate === null) { + firstBaseUpdate = firstPendingUpdate; + } else { + lastBaseUpdate.next = firstPendingUpdate; + } - return; - } // Dedup strategy: Warn once per component. + lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then + // we need to transfer the updates to that queue, too. Because the base + // queue is a singly-linked list with no cycles, we can append to both + // lists and take advantage of structural sharing. + // TODO: Pass `current` as argument - if (didWarnAboutLegacyContext.has(fiber.type)) { - return; - } + var current = workInProgress.alternate; - var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); + if (current !== null) { + // This is always non-null on a ClassComponent or HostRoot + var currentQueue = current.updateQueue; + var currentLastBaseUpdate = currentQueue.lastBaseUpdate; - if ( - fiber.type.contextTypes != null || - fiber.type.childContextTypes != null || - (instance !== null && typeof instance.getChildContext === "function") - ) { - if (warningsForRoot === undefined) { - warningsForRoot = []; - pendingLegacyContextWarning.set(strictRoot, warningsForRoot); - } + if (currentLastBaseUpdate !== lastBaseUpdate) { + if (currentLastBaseUpdate === null) { + currentQueue.firstBaseUpdate = firstPendingUpdate; + } else { + currentLastBaseUpdate.next = firstPendingUpdate; + } - warningsForRoot.push(fiber); - } - }; + currentQueue.lastBaseUpdate = lastPendingUpdate; + } + } + } // These values may change as we process the queue. - ReactStrictModeWarnings.flushLegacyContextWarning = function () { - pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) { - if (fiberArray.length === 0) { - return; - } + if (firstBaseUpdate !== null) { + // Iterate through the list of updates to compute the result. + var newState = queue.baseState; // TODO: Don't need to accumulate this. Instead, we can remove renderLanes + // from the original lanes. + + var newLanes = NoLanes; + var newBaseState = null; + var newFirstBaseUpdate = null; + var newLastBaseUpdate = null; + var update = firstBaseUpdate; - var firstFiber = fiberArray[0]; - var uniqueNames = new Set(); - fiberArray.forEach(function (fiber) { - uniqueNames.add(getComponentNameFromFiber(fiber) || "Component"); - didWarnAboutLegacyContext.add(fiber.type); - }); - var sortedNames = setToSortedString(uniqueNames); + do { + // An extra OffscreenLane bit is added to updates that were made to + // a hidden tree, so that we can distinguish them from updates that were + // already there when the tree was hidden. + var updateLane = removeLanes(update.lane, OffscreenLane); + var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then + // it's not a "base" update and we should disregard the extra base lanes + // that were added to renderLanes when we entered the Offscreen tree. + + var shouldSkipUpdate = isHiddenUpdate + ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) + : !isSubsetOfLanes(renderLanes, updateLane); + + if (shouldSkipUpdate) { + // Priority is insufficient. Skip this update. If this is the first + // skipped update, the previous update/state is the new base + // update/state. + var clone = { + lane: updateLane, + tag: update.tag, + payload: update.payload, + callback: update.callback, + next: null + }; - try { - setCurrentFiber(firstFiber); + if (newLastBaseUpdate === null) { + newFirstBaseUpdate = newLastBaseUpdate = clone; + newBaseState = newState; + } else { + newLastBaseUpdate = newLastBaseUpdate.next = clone; + } // Update the remaining priority in the queue. - 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 - ); - } finally { - resetCurrentFiber(); - } - }); - }; - - ReactStrictModeWarnings.discardPendingWarnings = function () { - pendingComponentWillMountWarnings = []; - pendingUNSAFE_ComponentWillMountWarnings = []; - pendingComponentWillReceivePropsWarnings = []; - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - pendingComponentWillUpdateWarnings = []; - pendingUNSAFE_ComponentWillUpdateWarnings = []; - pendingLegacyContextWarning = new Map(); - }; -} + newLanes = mergeLanes(newLanes, updateLane); + } else { + // This update does have sufficient priority. + if (newLastBaseUpdate !== null) { + var _clone = { + // This update is going to be committed so we never want uncommit + // it. Using NoLane works because 0 is a subset of all bitmasks, so + // this will never be skipped by the check above. + lane: NoLane, + tag: update.tag, + payload: update.payload, + // When this update is rebased, we should not fire its + // callback again. + callback: null, + next: null + }; + newLastBaseUpdate = newLastBaseUpdate.next = _clone; + } // Process this update. + + newState = getStateFromUpdate( + workInProgress, + queue, + update, + newState, + props, + instance + ); + var callback = update.callback; -/* - * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol - * and Temporal.* types. See https://github.com/facebook/react/pull/22064. - * - * The functions in this module will throw an easier-to-understand, - * easier-to-debug exception with a clear errors message message explaining the - * problem. (Instead of a confusing exception thrown inside the implementation - * of the `value` object). - */ -// $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. -function typeName(value) { - { - // toStringTag is needed for namespaced types like Temporal.Instant - var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; - var type = - (hasToStringTag && value[Symbol.toStringTag]) || - value.constructor.name || - "Object"; // $FlowFixMe[incompatible-return] - - return type; - } -} // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - -function willCoercionThrow(value) { - { - try { - testStringCoercion(value); - return false; - } catch (e) { - return true; - } - } -} + if (callback !== null) { + workInProgress.flags |= Callback; -function testStringCoercion(value) { - // If you ended up here by following an exception call stack, here's what's - // happened: you supplied an object or symbol value to React (as a prop, key, - // DOM attribute, CSS property, string ref, etc.) and when React tried to - // coerce it to a string using `'' + value`, an exception was thrown. - // - // The most common types that will cause this exception are `Symbol` instances - // and Temporal objects like `Temporal.Instant`. But any object that has a - // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this - // exception. (Library authors do this to prevent users from using built-in - // numeric operators like `+` or comparison operators like `>=` because custom - // methods are needed to perform accurate arithmetic or comparison.) - // - // To fix the problem, coerce this object or symbol value to a string before - // passing it to React. The most reliable way is usually `String(value)`. - // - // To find which value is throwing, check the browser or debugger console. - // Before this exception was thrown, there should be `console.error` output - // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the - // problem and how that type was used: key, atrribute, input value prop, etc. - // In most cases, this console output also shows the component and its - // ancestor components where the exception happened. - // - // eslint-disable-next-line react-internal/safe-string-coercion - return "" + value; -} -function checkPropStringCoercion(value, propName) { - { - if (willCoercionThrow(value)) { - error( - "The provided `%s` prop is an unsupported type %s." + - " This value must be coerced to a string before using it here.", - propName, - typeName(value) - ); + if (isHiddenUpdate) { + workInProgress.flags |= Visibility; + } - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) - } - } -} + var callbacks = queue.callbacks; -var ReactCurrentActQueue$3 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we -// detect this is caught by userspace, we'll log a warning in development. - -var SuspenseException = new Error( - "Suspense Exception: This is not a real error! It's an implementation " + - "detail of `use` to interrupt the current render. You must either " + - "rethrow it immediately, or move the `use` call outside of the " + - "`try/catch` block. Capturing without rethrowing will lead to " + - "unexpected behavior.\n\n" + - "To handle async errors, wrap your component in an error boundary, or " + - "call the promise's `.catch` method and pass the result to `use`" -); -var SuspenseyCommitException = new Error( - "Suspense Exception: This is not a real error, and should not leak into " + - "userspace. If you're seeing this, it's likely a bug in React." -); // This is a noop thenable that we use to trigger a fallback in throwException. -// TODO: It would be better to refactor throwException into multiple functions -// so we can trigger a fallback directly without having to check the type. But -// for now this will do. - -var noopSuspenseyCommitThenable = { - then: function () { - { - error( - "Internal React error: A listener was unexpectedly attached to a " + - '"noop" thenable. This is a bug in React. Please file an issue.' - ); - } - } -}; -function createThenableState() { - // The ThenableState is created the first time a component suspends. If it - // suspends again, we'll reuse the same state. - return []; -} -function isThenableResolved(thenable) { - var status = thenable.status; - return status === "fulfilled" || status === "rejected"; -} + if (callbacks === null) { + queue.callbacks = [callback]; + } else { + callbacks.push(callback); + } + } + } // $FlowFixMe[incompatible-type] we bail out when we get a null -function noop() {} - -function trackUsedThenable(thenableState, thenable, index) { - if (ReactCurrentActQueue$3.current !== null) { - ReactCurrentActQueue$3.didUsePromise = true; - } - - var previous = thenableState[index]; - - if (previous === undefined) { - thenableState.push(thenable); - } else { - if (previous !== thenable) { - // Reuse the previous thenable, and drop the new one. We can assume - // they represent the same value, because components are idempotent. - // Avoid an unhandled rejection errors for the Promises that we'll - // intentionally ignore. - thenable.then(noop, noop); - thenable = previous; - } - } // We use an expando to track the status and result of a thenable so that we - // can synchronously unwrap the value. Think of this as an extension of the - // Promise API, or a custom interface that is a superset of Thenable. - // - // If the thenable doesn't have a status, set it to "pending" and attach - // a listener that will update its status and result when it resolves. - - switch (thenable.status) { - case "fulfilled": { - var fulfilledValue = thenable.value; - return fulfilledValue; - } - - case "rejected": { - var rejectedError = thenable.reason; - checkIfUseWrappedInAsyncCatch(rejectedError); - throw rejectedError; - } - - default: { - if (typeof thenable.status === "string") { - // Only instrument the thenable if the status if not defined. If - // it's defined, but an unknown value, assume it's been instrumented by - // some custom userspace implementation. We treat it as "pending". - // Attach a dummy listener, to ensure that any lazy initialization can - // happen. Flight lazily parses JSON when the value is actually awaited. - thenable.then(noop, noop); - } else { - // This is an uncached thenable that we haven't seen before. - // Detect infinite ping loops caused by uncached promises. - var root = getWorkInProgressRoot(); + update = update.next; - if (root !== null && root.shellSuspendCounter > 100) { - // This root has suspended repeatedly in the shell without making any - // progress (i.e. committing something). This is highly suggestive of - // an infinite ping loop, often caused by an accidental Async Client - // Component. - // - // During a transition, we can suspend the work loop until the promise - // to resolve, but this is a sync render, so that's not an option. We - // also can't show a fallback, because none was provided. So our last - // resort is to throw an error. - // - // TODO: Remove this error in a future release. Other ways of handling - // this case include forcing a concurrent render, or putting the whole - // root into offscreen mode. - throw new Error( - "async/await is not yet supported in Client Components, only " + - "Server Components. This error is often caused by accidentally " + - "adding `'use client'` to a module that was originally written " + - "for the server." - ); - } + if (update === null) { + pendingQueue = queue.shared.pending; - var pendingThenable = thenable; - pendingThenable.status = "pending"; - pendingThenable.then( - function (fulfilledValue) { - if (thenable.status === "pending") { - var fulfilledThenable = thenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = fulfilledValue; - } - }, - function (error) { - if (thenable.status === "pending") { - var rejectedThenable = thenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = error; + if (pendingQueue === null) { + break; + } else { + // An update was scheduled from inside a reducer. Add the new + // pending updates to the end of the list and keep processing. + var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we + // unravel them when transferring them to the base queue. + + var _firstPendingUpdate = _lastPendingUpdate.next; + _lastPendingUpdate.next = null; + update = _firstPendingUpdate; + queue.lastBaseUpdate = _lastPendingUpdate; + queue.shared.pending = null; } } - ); // Check one more time in case the thenable resolved synchronously. + } while (true); - switch (thenable.status) { - case "fulfilled": { - var fulfilledThenable = thenable; - return fulfilledThenable.value; - } - - case "rejected": { - var rejectedThenable = thenable; - var _rejectedError = rejectedThenable.reason; - checkIfUseWrappedInAsyncCatch(_rejectedError); - throw _rejectedError; - } + if (newLastBaseUpdate === null) { + newBaseState = newState; } - } // Suspend. - // - // Throwing here is an implementation detail that allows us to unwind the - // call stack. But we shouldn't allow it to leak into userspace. Throw an - // opaque placeholder value instead of the actual thenable. If it doesn't - // get captured by the work loop, log a warning, because that means - // something in userspace must have caught it. - suspendedThenable = thenable; + queue.baseState = newBaseState; + queue.firstBaseUpdate = newFirstBaseUpdate; + queue.lastBaseUpdate = newLastBaseUpdate; - { - needsToResetSuspendedThenableDEV = true; + if (firstBaseUpdate === null) { + // `queue.lanes` is used for entangling transitions. We can set it back to + // zero once the queue is empty. + queue.shared.lanes = NoLanes; + } // Set the remaining expiration time to be whatever is remaining in the queue. + // This should be fine because the only two other things that contribute to + // expiration time are props and context. We're already in the middle of the + // begin phase by the time we start processing the queue, so we've already + // dealt with the props. Context in components that specify + // shouldComponentUpdate is tricky; but we'll have to account for + // that regardless. + + markSkippedUpdateLanes(newLanes); + workInProgress.lanes = newLanes; + workInProgress.memoizedState = newState; } - throw SuspenseException; + { + currentlyProcessingQueue = null; + } } - } -} -// passed to the rest of the Suspense implementation — which, for historical -// reasons, expects to receive a thenable. - -var suspendedThenable = null; -var needsToResetSuspendedThenableDEV = false; -function getSuspendedThenable() { - // This is called right after `use` suspends by throwing an exception. `use` - // throws an opaque value instead of the thenable itself so that it can't be - // caught in userspace. Then the work loop accesses the actual thenable using - // this function. - if (suspendedThenable === null) { - throw new Error( - "Expected a suspended thenable. This is a bug in React. Please file " + - "an issue." - ); - } - var thenable = suspendedThenable; - suspendedThenable = null; - - { - needsToResetSuspendedThenableDEV = false; - } + function callCallback(callback, context) { + if (typeof callback !== "function") { + throw new Error( + "Invalid argument passed as callback. Expected a function. Instead " + + ("received: " + callback) + ); + } - return thenable; -} -function checkIfUseWrappedInTryCatch() { - { - // This was set right before SuspenseException was thrown, and it should - // have been cleared when the exception was handled. If it wasn't, - // it must have been caught by userspace. - if (needsToResetSuspendedThenableDEV) { - needsToResetSuspendedThenableDEV = false; - return true; + callback.call(context); } - } - - return false; -} -function checkIfUseWrappedInAsyncCatch(rejectedReason) { - // This check runs in prod, too, because it prevents a more confusing - // downstream error, where SuspenseException is caught by a promise and - // thrown asynchronously. - // TODO: Another way to prevent SuspenseException from leaking into an async - // execution context is to check the dispatcher every time `use` is called, - // or some equivalent. That might be preferable for other reasons, too, since - // it matches how we prevent similar mistakes for other hooks. - if (rejectedReason === SuspenseException) { - throw new Error( - "Hooks are not supported inside an async component. This " + - "error is often caused by accidentally adding `'use client'` " + - "to a module that was originally written for the server." - ); - } -} - -var thenableState$1 = null; -var thenableIndexCounter$1 = 0; -var didWarnAboutMaps; -var didWarnAboutGenerators; -var didWarnAboutStringRefs; -var ownerHasKeyUseWarning; -var ownerHasFunctionTypeWarning; - -var warnForMissingKey = function (child, returnFiber) {}; - -{ - didWarnAboutMaps = false; - didWarnAboutGenerators = false; - didWarnAboutStringRefs = {}; - /** - * Warn if there's no key explicitly set on dynamic arrays of children or - * object keys are not valid. This allows us to keep track of children between - * updates. - */ - ownerHasKeyUseWarning = {}; - ownerHasFunctionTypeWarning = {}; - - warnForMissingKey = function (child, returnFiber) { - if (child === null || typeof child !== "object") { - return; + function resetHasForceUpdateBeforeProcessing() { + hasForceUpdate = false; } - - if (!child._store || child._store.validated || child.key != null) { - return; + function checkHasForceUpdateAfterProcessing() { + return hasForceUpdate; } + function deferHiddenCallbacks(updateQueue) { + // When an update finishes on a hidden component, its callback should not + // be fired until/unless the component is made visible again. Stash the + // callback on the shared queue object so it can be fired later. + var newHiddenCallbacks = updateQueue.callbacks; - if (typeof child._store !== "object") { - 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." - ); - } // $FlowFixMe[cannot-write] unable to narrow type from mixed to writable object - - child._store.validated = true; - var componentName = getComponentNameFromFiber(returnFiber) || "Component"; + if (newHiddenCallbacks !== null) { + var existingHiddenCallbacks = updateQueue.shared.hiddenCallbacks; - if (ownerHasKeyUseWarning[componentName]) { - return; + if (existingHiddenCallbacks === null) { + updateQueue.shared.hiddenCallbacks = newHiddenCallbacks; + } else { + updateQueue.shared.hiddenCallbacks = + existingHiddenCallbacks.concat(newHiddenCallbacks); + } + } } + function commitHiddenCallbacks(updateQueue, context) { + // This component is switching from hidden -> visible. Commit any callbacks + // that were previously deferred. + var hiddenCallbacks = updateQueue.shared.hiddenCallbacks; - ownerHasKeyUseWarning[componentName] = true; + if (hiddenCallbacks !== null) { + updateQueue.shared.hiddenCallbacks = null; - error( - "Each child in a list should have a unique " + - '"key" prop. See https://reactjs.org/link/warning-keys for ' + - "more information." - ); - }; -} - -function isReactClass(type) { - return type.prototype && type.prototype.isReactComponent; -} - -function unwrapThenable(thenable) { - var index = thenableIndexCounter$1; - thenableIndexCounter$1 += 1; - - if (thenableState$1 === null) { - thenableState$1 = createThenableState(); - } - - return trackUsedThenable(thenableState$1, thenable, index); -} - -function coerceRef(returnFiber, current, element) { - var mixedRef = element.ref; - - if ( - mixedRef !== null && - typeof mixedRef !== "function" && - typeof mixedRef !== "object" - ) { - { - if ( - // We warn in ReactElement.js if owner and self are equal for string refs - // because these cannot be automatically converted to an arrow function - // using a codemod. Therefore, we don't have to warn about string refs again. - !( - element._owner && - element._self && - element._owner.stateNode !== element._self - ) && // Will already throw with "Function components cannot have string refs" - !(element._owner && element._owner.tag !== ClassComponent) && // Will already warn with "Function components cannot be given refs" - !(typeof element.type === "function" && !isReactClass(element.type)) && // Will already throw with "Element ref was specified as a string (someStringRef) but no owner was set" - element._owner - ) { - var componentName = - getComponentNameFromFiber(returnFiber) || "Component"; - - if (!didWarnAboutStringRefs[componentName]) { - 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 - ); - - didWarnAboutStringRefs[componentName] = true; + for (var i = 0; i < hiddenCallbacks.length; i++) { + var callback = hiddenCallbacks[i]; + callCallback(callback, context); } } } + function commitCallbacks(updateQueue, context) { + var callbacks = updateQueue.callbacks; - if (element._owner) { - var owner = element._owner; - var inst; + if (callbacks !== null) { + updateQueue.callbacks = null; - if (owner) { - var ownerFiber = owner; - - if (ownerFiber.tag !== ClassComponent) { - 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" - ); + for (var i = 0; i < callbacks.length; i++) { + var callback = callbacks[i]; + callCallback(callback, context); } - - inst = ownerFiber.stateNode; } + } - if (!inst) { - throw new Error( - "Missing owner for string ref " + - mixedRef + - ". This error is likely caused by a " + - "bug in React. Please file an issue." - ); - } // Assigning this to a const so Flow knows it won't change in the closure - - var resolvedInst = inst; + /** + * Performs equality by iterating through keys on an object and returning false + * when any key has values which are not strictly equal between the arguments. + * Returns true when the values of all keys are strictly equal. + */ - { - checkPropStringCoercion(mixedRef, "ref"); + function shallowEqual(objA, objB) { + if (objectIs(objA, objB)) { + return true; } - var stringRef = "" + mixedRef; // Check if previous string ref matches new string ref - if ( - current !== null && - current.ref !== null && - typeof current.ref === "function" && - current.ref._stringRef === stringRef + typeof objA !== "object" || + objA === null || + typeof objB !== "object" || + objB === null ) { - return current.ref; + return false; } - var ref = function (value) { - var refs = resolvedInst.refs; + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); - if (value === null) { - delete refs[stringRef]; - } else { - refs[stringRef] = value; - } - }; + if (keysA.length !== keysB.length) { + return false; + } // Test for A's keys different from B. - ref._stringRef = stringRef; - return ref; - } else { - if (typeof mixedRef !== "string") { - throw new Error( - "Expected ref to be a function, a string, an object returned by React.createRef(), or null." - ); - } + for (var i = 0; i < keysA.length; i++) { + var currentKey = keysA[i]; - if (!element._owner) { - 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." - ); + if ( + !hasOwnProperty.call(objB, currentKey) || // $FlowFixMe[incompatible-use] lost refinement of `objB` + !objectIs(objA[currentKey], objB[currentKey]) + ) { + return false; + } } + + return true; } - } - return mixedRef; -} + function describeFiber(fiber) { + switch (fiber.tag) { + case HostHoistable: + case HostSingleton: + case HostComponent: + return describeBuiltInComponentFrame(fiber.type); -function throwOnInvalidObjectType(returnFiber, newChild) { - // $FlowFixMe[method-unbinding] - var childString = Object.prototype.toString.call(newChild); - 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." - ); -} + case LazyComponent: + return describeBuiltInComponentFrame("Lazy"); -function warnOnFunctionType(returnFiber) { - { - var componentName = getComponentNameFromFiber(returnFiber) || "Component"; + case SuspenseComponent: + return describeBuiltInComponentFrame("Suspense"); - if (ownerHasFunctionTypeWarning[componentName]) { - return; - } + case SuspenseListComponent: + return describeBuiltInComponentFrame("SuspenseList"); - ownerHasFunctionTypeWarning[componentName] = true; + case FunctionComponent: + case IndeterminateComponent: + case SimpleMemoComponent: + return describeFunctionComponentFrame(fiber.type); - error( - "Functions are not valid as a React child. This may happen if " + - "you return a Component instead of from render. " + - "Or maybe you meant to call this function rather than return it." - ); - } -} + case ForwardRef: + return describeFunctionComponentFrame(fiber.type.render); -function resolveLazy(lazyType) { - var payload = lazyType._payload; - var init = lazyType._init; - return init(payload); -} // This wrapper function exists because I expect to clone the code in each path -// to be able to optimize each path individually by branching early. This needs -// a compiler or we can do it manually. Helpers that don't need this branching -// live outside of this function. + case ClassComponent: + return describeClassComponentFrame(fiber.type); -function createChildReconciler(shouldTrackSideEffects) { - function deleteChild(returnFiber, childToDelete) { - if (!shouldTrackSideEffects) { - // Noop. - return; + default: + return ""; + } } - var deletions = returnFiber.deletions; - - if (deletions === null) { - returnFiber.deletions = [childToDelete]; - returnFiber.flags |= ChildDeletion; - } else { - deletions.push(childToDelete); - } - } + function getStackByFiberInDevAndProd(workInProgress) { + try { + var info = ""; + var node = workInProgress; - function deleteRemainingChildren(returnFiber, currentFirstChild) { - if (!shouldTrackSideEffects) { - // Noop. - return null; - } // TODO: For the shouldClone case, this could be micro-optimized a bit by - // assuming that after the first child we've already added everything. + do { + info += describeFiber(node); // $FlowFixMe[incompatible-type] we bail out when we get a null - var childToDelete = currentFirstChild; + node = node.return; + } while (node); - while (childToDelete !== null) { - deleteChild(returnFiber, childToDelete); - childToDelete = childToDelete.sibling; + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; + } } - return null; - } + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + var current = null; + var isRendering = false; + function getCurrentFiberOwnerNameInDevOrNull() { + { + if (current === null) { + return null; + } - function mapRemainingChildren(returnFiber, currentFirstChild) { - // Add the remaining children to a temporary map so that we can find them by - // keys quickly. Implicit (null) keys get added to this set with their index - // instead. - var existingChildren = new Map(); - var existingChild = currentFirstChild; + var owner = current._debugOwner; - while (existingChild !== null) { - if (existingChild.key !== null) { - existingChildren.set(existingChild.key, existingChild); - } else { - existingChildren.set(existingChild.index, existingChild); + if (owner !== null && typeof owner !== "undefined") { + return getComponentNameFromFiber(owner); + } } - existingChild = existingChild.sibling; + return null; } - return existingChildren; - } - - function useFiber(fiber, pendingProps) { - // We currently set sibling to null and index to 0 here because it is easy - // to forget to do before returning it. E.g. for the single child case. - var clone = createWorkInProgress(fiber, pendingProps); - clone.index = 0; - clone.sibling = null; - return clone; - } - - function placeChild(newFiber, lastPlacedIndex, newIndex) { - newFiber.index = newIndex; + function getCurrentFiberStackInDev() { + { + if (current === null) { + return ""; + } // Safe because if current fiber exists, we are reconciling, + // and it is guaranteed to be the work-in-progress version. - if (!shouldTrackSideEffects) { - // During hydration, the useId algorithm needs to know which fibers are - // part of a list of children (arrays, iterators). - newFiber.flags |= Forked; - return lastPlacedIndex; + return getStackByFiberInDevAndProd(current); + } } - var current = newFiber.alternate; - - if (current !== null) { - var oldIndex = current.index; - - if (oldIndex < lastPlacedIndex) { - // This is a move. - newFiber.flags |= Placement | PlacementDEV; - return lastPlacedIndex; - } else { - // This item can stay in place. - return oldIndex; + function resetCurrentFiber() { + { + ReactDebugCurrentFrame.getCurrentStack = null; + current = null; + isRendering = false; } - } else { - // This is an insertion. - newFiber.flags |= Placement | PlacementDEV; - return lastPlacedIndex; } - } - - function placeSingleChild(newFiber) { - // This is simpler for the single child case. We only need to do a - // placement for inserting new children. - if (shouldTrackSideEffects && newFiber.alternate === null) { - newFiber.flags |= Placement | PlacementDEV; + function setCurrentFiber(fiber) { + { + ReactDebugCurrentFrame.getCurrentStack = + fiber === null ? null : getCurrentFiberStackInDev; + current = fiber; + isRendering = false; + } } - - return newFiber; - } - - function updateTextNode(returnFiber, current, textContent, lanes) { - if (current === null || current.tag !== HostText) { - // Insert - var created = createFiberFromText(textContent, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, textContent); - existing.return = returnFiber; - return existing; + function getCurrentFiber() { + { + return current; + } + } + function setIsRendering(rendering) { + { + isRendering = rendering; + } } - } - function updateElement(returnFiber, current, element, lanes) { - var elementType = element.type; + var ReactStrictModeWarnings = { + recordUnsafeLifecycleWarnings: function (fiber, instance) {}, + flushPendingUnsafeLifecycleWarnings: function () {}, + recordLegacyContextWarning: function (fiber, instance) {}, + flushLegacyContextWarning: function () {}, + discardPendingWarnings: function () {} + }; - if (elementType === REACT_FRAGMENT_TYPE) { - return updateFragment( - returnFiber, - current, - element.props.children, - lanes, - element.key - ); - } + { + var findStrictRoot = function (fiber) { + var maybeStrictRoot = null; + var node = fiber; - if (current !== null) { - if ( - current.elementType === elementType || // Keep this check inline so it only runs on the false path: - isCompatibleFamilyForHotReloading(current, element) || // Lazy types should reconcile their resolved type. - // We need to do this after the Hot Reloading check above, - // because hot reloading has different semantics than prod because - // it doesn't resuspend. So we can't let the call below suspend. - (typeof elementType === "object" && - elementType !== null && - elementType.$$typeof === REACT_LAZY_TYPE && - resolveLazy(elementType) === current.type) - ) { - // Move based on index - var existing = useFiber(current, element.props); - existing.ref = coerceRef(returnFiber, current, element); - existing.return = returnFiber; + while (node !== null) { + if (node.mode & StrictLegacyMode) { + maybeStrictRoot = node; + } - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; + node = node.return; } - return existing; - } - } // Insert + return maybeStrictRoot; + }; - var created = createFiberFromElement(element, returnFiber.mode, lanes); - created.ref = coerceRef(returnFiber, current, element); - created.return = returnFiber; - return created; - } + var setToSortedString = function (set) { + var array = []; + set.forEach(function (value) { + array.push(value); + }); + return array.sort().join(", "); + }; - function updatePortal(returnFiber, current, portal, lanes) { - if ( - current === null || - current.tag !== HostPortal || - current.stateNode.containerInfo !== portal.containerInfo || - current.stateNode.implementation !== portal.implementation - ) { - // Insert - var created = createFiberFromPortal(portal, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, portal.children || []); - existing.return = returnFiber; - return existing; - } - } - - function updateFragment(returnFiber, current, fragment, lanes, key) { - if (current === null || current.tag !== Fragment) { - // Insert - var created = createFiberFromFragment( - fragment, - returnFiber.mode, - lanes, - key - ); - created.return = returnFiber; - return created; - } else { - // Update - var existing = useFiber(current, fragment); - existing.return = returnFiber; - return existing; - } - } + var pendingComponentWillMountWarnings = []; + var pendingUNSAFE_ComponentWillMountWarnings = []; + var pendingComponentWillReceivePropsWarnings = []; + var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + var pendingComponentWillUpdateWarnings = []; + var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. - function createChild(returnFiber, newChild, lanes) { - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys. If the previous node is implicitly keyed - // we can continue to replace it without aborting even if it is not a text - // node. - var created = createFiberFromText("" + newChild, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } - - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - var _created = createFiberFromElement( - newChild, - returnFiber.mode, - lanes - ); + var didWarnAboutUnsafeLifecycles = new Set(); - _created.ref = coerceRef(returnFiber, null, newChild); - _created.return = returnFiber; - return _created; + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function ( + fiber, + instance + ) { + // Dedupe strategy: Warn once per component. + if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { + return; } - case REACT_PORTAL_TYPE: { - var _created2 = createFiberFromPortal( - newChild, - returnFiber.mode, - lanes - ); + if ( + typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + pendingComponentWillMountWarnings.push(fiber); + } - _created2.return = returnFiber; - return _created2; + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillMount === "function" + ) { + pendingUNSAFE_ComponentWillMountWarnings.push(fiber); } - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return createChild(returnFiber, init(payload), lanes); + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== + true + ) { + pendingComponentWillReceivePropsWarnings.push(fiber); } - } - if (isArray(newChild) || getIteratorFn(newChild)) { - var _created3 = createFiberFromFragment( - newChild, - returnFiber.mode, - lanes, - null - ); + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); + } - _created3.return = returnFiber; - return _created3; - } // Usable node types - // - // Unwrap the inner value and recursively call this function again. + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + pendingComponentWillUpdateWarnings.push(fiber); + } - if (typeof newChild.then === "function") { - var thenable = newChild; - return createChild(returnFiber, unwrapThenable(thenable), lanes); - } + if ( + fiber.mode & StrictLegacyMode && + typeof instance.UNSAFE_componentWillUpdate === "function" + ) { + pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); + } + }; - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return createChild( - returnFiber, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes - ); - } + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = + function () { + // We do an initial pass to gather component names + var componentWillMountUniqueNames = new Set(); - throwOnInvalidObjectType(returnFiber, newChild); - } + if (pendingComponentWillMountWarnings.length > 0) { + pendingComponentWillMountWarnings.forEach(function (fiber) { + componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillMountWarnings = []; + } - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } - } + var UNSAFE_componentWillMountUniqueNames = new Set(); - return null; - } + if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { + pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) { + UNSAFE_componentWillMountUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillMountWarnings = []; + } - function updateSlot(returnFiber, oldFiber, newChild, lanes) { - // Update the fiber if the keys match, otherwise return null. - var key = oldFiber !== null ? oldFiber.key : null; + var componentWillReceivePropsUniqueNames = new Set(); - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys. If the previous node is implicitly keyed - // we can continue to replace it without aborting even if it is not a text - // node. - if (key !== null) { - return null; - } + if (pendingComponentWillReceivePropsWarnings.length > 0) { + pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { + componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillReceivePropsWarnings = []; + } - return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); - } + var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - if (newChild.key === key) { - return updateElement(returnFiber, oldFiber, newChild, lanes); - } else { - return null; + if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach( + function (fiber) { + UNSAFE_componentWillReceivePropsUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + } + ); + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; } - } - case REACT_PORTAL_TYPE: { - if (newChild.key === key) { - return updatePortal(returnFiber, oldFiber, newChild, lanes); - } else { - return null; - } - } + var componentWillUpdateUniqueNames = new Set(); - case REACT_LAZY_TYPE: { - var payload = newChild._payload; - var init = newChild._init; - return updateSlot(returnFiber, oldFiber, init(payload), lanes); - } - } + if (pendingComponentWillUpdateWarnings.length > 0) { + pendingComponentWillUpdateWarnings.forEach(function (fiber) { + componentWillUpdateUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillUpdateWarnings = []; + } - if (isArray(newChild) || getIteratorFn(newChild)) { - if (key !== null) { - return null; - } + var UNSAFE_componentWillUpdateUniqueNames = new Set(); - return updateFragment(returnFiber, oldFiber, newChild, lanes, null); - } // Usable node types - // - // Unwrap the inner value and recursively call this function again. + if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { + pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function (fiber) { + UNSAFE_componentWillUpdateUniqueNames.add( + getComponentNameFromFiber(fiber) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillUpdateWarnings = []; + } // Finally, we flush all the warnings + // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' - if (typeof newChild.then === "function") { - var thenable = newChild; - return updateSlot( - returnFiber, - oldFiber, - unwrapThenable(thenable), - lanes - ); - } + if (UNSAFE_componentWillMountUniqueNames.size > 0) { + var sortedNames = setToSortedString( + UNSAFE_componentWillMountUniqueNames + ); - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return updateSlot( - returnFiber, - oldFiber, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes - ); - } + 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 + ); + } - throwOnInvalidObjectType(returnFiber, newChild); - } + if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames = setToSortedString( + UNSAFE_componentWillReceivePropsUniqueNames + ); - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } - } + 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 + ); + } - return null; - } + if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { + var _sortedNames2 = setToSortedString( + UNSAFE_componentWillUpdateUniqueNames + ); - function updateFromMap( - existingChildren, - returnFiber, - newIdx, - newChild, - lanes - ) { - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - // Text nodes don't have keys, so we neither have to check the old nor - // new node for the key. If both are text nodes, they match. - var matchedFiber = existingChildren.get(newIdx) || null; - return updateTextNode(returnFiber, matchedFiber, "" + newChild, lanes); - } + 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 + ); + } - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: { - var _matchedFiber = - existingChildren.get( - newChild.key === null ? newIdx : newChild.key - ) || null; + if (componentWillMountUniqueNames.size > 0) { + var _sortedNames3 = setToSortedString( + componentWillMountUniqueNames + ); - return updateElement(returnFiber, _matchedFiber, newChild, lanes); - } + 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 + ); + } - case REACT_PORTAL_TYPE: { - var _matchedFiber2 = - existingChildren.get( - newChild.key === null ? newIdx : newChild.key - ) || null; + if (componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames4 = setToSortedString( + componentWillReceivePropsUniqueNames + ); - return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); - } + 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 + ); + } - case REACT_LAZY_TYPE: - var payload = newChild._payload; - var init = newChild._init; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - init(payload), - lanes - ); - } + if (componentWillUpdateUniqueNames.size > 0) { + var _sortedNames5 = setToSortedString( + componentWillUpdateUniqueNames + ); - if (isArray(newChild) || getIteratorFn(newChild)) { - var _matchedFiber3 = existingChildren.get(newIdx) || null; + 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 + ); + } + }; - return updateFragment( - returnFiber, - _matchedFiber3, - newChild, - lanes, - null - ); - } // Usable node types - // - // Unwrap the inner value and recursively call this function again. + var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. - if (typeof newChild.then === "function") { - var thenable = newChild; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - unwrapThenable(thenable), - lanes - ); - } + var didWarnAboutLegacyContext = new Set(); - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ReactStrictModeWarnings.recordLegacyContextWarning = function ( + fiber, + instance ) { - var context = newChild; - return updateFromMap( - existingChildren, - returnFiber, - newIdx, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes - ); - } + var strictRoot = findStrictRoot(fiber); - throwOnInvalidObjectType(returnFiber, newChild); - } - - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } - } + if (strictRoot === null) { + 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." + ); - return null; - } - /** - * Warns if there is a duplicate or missing key - */ + return; + } // Dedup strategy: Warn once per component. - function warnOnInvalidKey(child, knownKeys, returnFiber) { - { - if (typeof child !== "object" || child === null) { - return knownKeys; - } + if (didWarnAboutLegacyContext.has(fiber.type)) { + return; + } - switch (child.$$typeof) { - case REACT_ELEMENT_TYPE: - case REACT_PORTAL_TYPE: - warnForMissingKey(child, returnFiber); - var key = child.key; + var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); - if (typeof key !== "string") { - break; + if ( + fiber.type.contextTypes != null || + fiber.type.childContextTypes != null || + (instance !== null && typeof instance.getChildContext === "function") + ) { + if (warningsForRoot === undefined) { + warningsForRoot = []; + pendingLegacyContextWarning.set(strictRoot, warningsForRoot); } - if (knownKeys === null) { - knownKeys = new Set(); - knownKeys.add(key); - break; - } + warningsForRoot.push(fiber); + } + }; - if (!knownKeys.has(key)) { - knownKeys.add(key); - break; + ReactStrictModeWarnings.flushLegacyContextWarning = function () { + pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) { + if (fiberArray.length === 0) { + return; } - 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 - ); - - break; + var firstFiber = fiberArray[0]; + var uniqueNames = new Set(); + fiberArray.forEach(function (fiber) { + uniqueNames.add(getComponentNameFromFiber(fiber) || "Component"); + didWarnAboutLegacyContext.add(fiber.type); + }); + var sortedNames = setToSortedString(uniqueNames); - case REACT_LAZY_TYPE: - var payload = child._payload; - var init = child._init; - warnOnInvalidKey(init(payload), knownKeys, returnFiber); - break; - } - } + try { + setCurrentFiber(firstFiber); - return knownKeys; - } - - function reconcileChildrenArray( - returnFiber, - currentFirstChild, - newChildren, - lanes - ) { - // This algorithm can't optimize by searching from both ends since we - // don't have backpointers on fibers. I'm trying to see how far we can get - // with that model. If it ends up not being worth the tradeoffs, we can - // add it later. - // Even with a two ended optimization, we'd want to optimize for the case - // where there are few changes and brute force the comparison instead of - // going for the Map. It'd like to explore hitting that path first in - // forward-only mode and only go for the Map once we notice that we need - // lots of look ahead. This doesn't handle reversal as well as two ended - // search but that's unusual. Besides, for the two ended optimization to - // work on Iterables, we'd need to copy the whole set. - // In this first iteration, we'll just live with hitting the bad case - // (adding everything to a Map) in for every insert/move. - // If you change this code, also update reconcileChildrenIterator() which - // uses the same algorithm. - { - // First, validate keys. - var knownKeys = null; + 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 + ); + } finally { + resetCurrentFiber(); + } + }); + }; - for (var i = 0; i < newChildren.length; i++) { - var child = newChildren[i]; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); - } + ReactStrictModeWarnings.discardPendingWarnings = function () { + pendingComponentWillMountWarnings = []; + pendingUNSAFE_ComponentWillMountWarnings = []; + pendingComponentWillReceivePropsWarnings = []; + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + pendingComponentWillUpdateWarnings = []; + pendingUNSAFE_ComponentWillUpdateWarnings = []; + pendingLegacyContextWarning = new Map(); + }; } - var resultingFirstChild = null; - var previousNewFiber = null; - var oldFiber = currentFirstChild; - var lastPlacedIndex = 0; - var newIdx = 0; - var nextOldFiber = null; + /* + * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol + * and Temporal.* types. See https://github.com/facebook/react/pull/22064. + * + * The functions in this module will throw an easier-to-understand, + * easier-to-debug exception with a clear errors message message explaining the + * problem. (Instead of a confusing exception thrown inside the implementation + * of the `value` object). + */ + // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. + function typeName(value) { + { + // toStringTag is needed for namespaced types like Temporal.Instant + var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; + var type = + (hasToStringTag && value[Symbol.toStringTag]) || + value.constructor.name || + "Object"; // $FlowFixMe[incompatible-return] - for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { - if (oldFiber.index > newIdx) { - nextOldFiber = oldFiber; - oldFiber = null; - } else { - nextOldFiber = oldFiber.sibling; + return type; } + } // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - var newFiber = updateSlot( - returnFiber, - oldFiber, - newChildren[newIdx], - lanes - ); - - if (newFiber === null) { - // TODO: This breaks on empty slots like null children. That's - // unfortunate because it triggers the slow path all the time. We need - // a better way to communicate whether this was a miss or null, - // boolean, undefined, etc. - if (oldFiber === null) { - oldFiber = nextOldFiber; + function willCoercionThrow(value) { + { + try { + testStringCoercion(value); + return false; + } catch (e) { + return true; } - - break; } + } + + function testStringCoercion(value) { + // If you ended up here by following an exception call stack, here's what's + // happened: you supplied an object or symbol value to React (as a prop, key, + // DOM attribute, CSS property, string ref, etc.) and when React tried to + // coerce it to a string using `'' + value`, an exception was thrown. + // + // The most common types that will cause this exception are `Symbol` instances + // and Temporal objects like `Temporal.Instant`. But any object that has a + // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this + // exception. (Library authors do this to prevent users from using built-in + // numeric operators like `+` or comparison operators like `>=` because custom + // methods are needed to perform accurate arithmetic or comparison.) + // + // To fix the problem, coerce this object or symbol value to a string before + // passing it to React. The most reliable way is usually `String(value)`. + // + // To find which value is throwing, check the browser or debugger console. + // Before this exception was thrown, there should be `console.error` output + // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the + // problem and how that type was used: key, atrribute, input value prop, etc. + // In most cases, this console output also shows the component and its + // ancestor components where the exception happened. + // + // eslint-disable-next-line react-internal/safe-string-coercion + return "" + value; + } + function checkPropStringCoercion(value, propName) { + { + if (willCoercionThrow(value)) { + error( + "The provided `%s` prop is an unsupported type %s." + + " This value must be coerced to a string before using it here.", + propName, + typeName(value) + ); - if (shouldTrackSideEffects) { - if (oldFiber && newFiber.alternate === null) { - // We matched the slot, but we didn't reuse the existing fiber, so we - // need to delete the existing child. - deleteChild(returnFiber, oldFiber); + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } } + } - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + var ReactCurrentActQueue$3 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we + // detect this is caught by userspace, we'll log a warning in development. - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = newFiber; - } else { - // TODO: Defer siblings if we're not at the right index for this slot. - // I.e. if we had null values before, then we want to defer this - // for each null value. However, we also don't want to call updateSlot - // with the previous one. - previousNewFiber.sibling = newFiber; + var SuspenseException = new Error( + "Suspense Exception: This is not a real error! It's an implementation " + + "detail of `use` to interrupt the current render. You must either " + + "rethrow it immediately, or move the `use` call outside of the " + + "`try/catch` block. Capturing without rethrowing will lead to " + + "unexpected behavior.\n\n" + + "To handle async errors, wrap your component in an error boundary, or " + + "call the promise's `.catch` method and pass the result to `use`" + ); + var SuspenseyCommitException = new Error( + "Suspense Exception: This is not a real error, and should not leak into " + + "userspace. If you're seeing this, it's likely a bug in React." + ); // This is a noop thenable that we use to trigger a fallback in throwException. + // TODO: It would be better to refactor throwException into multiple functions + // so we can trigger a fallback directly without having to check the type. But + // for now this will do. + + var noopSuspenseyCommitThenable = { + then: function () { + { + error( + "Internal React error: A listener was unexpectedly attached to a " + + '"noop" thenable. This is a bug in React. Please file an issue.' + ); + } } - - previousNewFiber = newFiber; - oldFiber = nextOldFiber; + }; + function createThenableState() { + // The ThenableState is created the first time a component suspends. If it + // suspends again, we'll reuse the same state. + return []; + } + function isThenableResolved(thenable) { + var status = thenable.status; + return status === "fulfilled" || status === "rejected"; } - if (newIdx === newChildren.length) { - // We've reached the end of the new children. We can delete the rest. - deleteRemainingChildren(returnFiber, oldFiber); + function noop() {} - return resultingFirstChild; - } + function trackUsedThenable(thenableState, thenable, index) { + if (ReactCurrentActQueue$3.current !== null) { + ReactCurrentActQueue$3.didUsePromise = true; + } - if (oldFiber === null) { - // If we don't have any more existing children we can choose a fast path - // since the rest will all be insertions. - for (; newIdx < newChildren.length; newIdx++) { - var _newFiber = createChild(returnFiber, newChildren[newIdx], lanes); + var previous = thenableState[index]; - if (_newFiber === null) { - continue; - } + if (previous === undefined) { + thenableState.push(thenable); + } else { + if (previous !== thenable) { + // Reuse the previous thenable, and drop the new one. We can assume + // they represent the same value, because components are idempotent. + // Avoid an unhandled rejection errors for the Promises that we'll + // intentionally ignore. + thenable.then(noop, noop); + thenable = previous; + } + } // We use an expando to track the status and result of a thenable so that we + // can synchronously unwrap the value. Think of this as an extension of the + // Promise API, or a custom interface that is a superset of Thenable. + // + // If the thenable doesn't have a status, set it to "pending" and attach + // a listener that will update its status and result when it resolves. - lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); + switch (thenable.status) { + case "fulfilled": { + var fulfilledValue = thenable.value; + return fulfilledValue; + } - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = _newFiber; - } else { - previousNewFiber.sibling = _newFiber; + case "rejected": { + var rejectedError = thenable.reason; + checkIfUseWrappedInAsyncCatch(rejectedError); + throw rejectedError; } - previousNewFiber = _newFiber; - } + default: { + if (typeof thenable.status === "string") { + // Only instrument the thenable if the status if not defined. If + // it's defined, but an unknown value, assume it's been instrumented by + // some custom userspace implementation. We treat it as "pending". + // Attach a dummy listener, to ensure that any lazy initialization can + // happen. Flight lazily parses JSON when the value is actually awaited. + thenable.then(noop, noop); + } else { + // This is an uncached thenable that we haven't seen before. + // Detect infinite ping loops caused by uncached promises. + var root = getWorkInProgressRoot(); + + if (root !== null && root.shellSuspendCounter > 100) { + // This root has suspended repeatedly in the shell without making any + // progress (i.e. committing something). This is highly suggestive of + // an infinite ping loop, often caused by an accidental Async Client + // Component. + // + // During a transition, we can suspend the work loop until the promise + // to resolve, but this is a sync render, so that's not an option. We + // also can't show a fallback, because none was provided. So our last + // resort is to throw an error. + // + // TODO: Remove this error in a future release. Other ways of handling + // this case include forcing a concurrent render, or putting the whole + // root into offscreen mode. + throw new Error( + "async/await is not yet supported in Client Components, only " + + "Server Components. This error is often caused by accidentally " + + "adding `'use client'` to a module that was originally written " + + "for the server." + ); + } - return resultingFirstChild; - } // Add all children to a key map for quick lookups. + var pendingThenable = thenable; + pendingThenable.status = "pending"; + pendingThenable.then( + function (fulfilledValue) { + if (thenable.status === "pending") { + var fulfilledThenable = thenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = fulfilledValue; + } + }, + function (error) { + if (thenable.status === "pending") { + var rejectedThenable = thenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; + } + } + ); // Check one more time in case the thenable resolved synchronously. - var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + switch (thenable.status) { + case "fulfilled": { + var fulfilledThenable = thenable; + return fulfilledThenable.value; + } - for (; newIdx < newChildren.length; newIdx++) { - var _newFiber2 = updateFromMap( - existingChildren, - returnFiber, - newIdx, - newChildren[newIdx], - lanes - ); + case "rejected": { + var rejectedThenable = thenable; + var _rejectedError = rejectedThenable.reason; + checkIfUseWrappedInAsyncCatch(_rejectedError); + throw _rejectedError; + } + } + } // Suspend. + // + // Throwing here is an implementation detail that allows us to unwind the + // call stack. But we shouldn't allow it to leak into userspace. Throw an + // opaque placeholder value instead of the actual thenable. If it doesn't + // get captured by the work loop, log a warning, because that means + // something in userspace must have caught it. - if (_newFiber2 !== null) { - if (shouldTrackSideEffects) { - if (_newFiber2.alternate !== null) { - // The new fiber is a work in progress, but if there exists a - // current, that means that we reused the fiber. We need to delete - // it from the child list so that we don't add it to the deletion - // list. - existingChildren.delete( - _newFiber2.key === null ? newIdx : _newFiber2.key - ); + suspendedThenable = thenable; + + { + needsToResetSuspendedThenableDEV = true; } + + throw SuspenseException; } + } + } + // passed to the rest of the Suspense implementation — which, for historical + // reasons, expects to receive a thenable. - lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); + var suspendedThenable = null; + var needsToResetSuspendedThenableDEV = false; + function getSuspendedThenable() { + // This is called right after `use` suspends by throwing an exception. `use` + // throws an opaque value instead of the thenable itself so that it can't be + // caught in userspace. Then the work loop accesses the actual thenable using + // this function. + if (suspendedThenable === null) { + throw new Error( + "Expected a suspended thenable. This is a bug in React. Please file " + + "an issue." + ); + } - if (previousNewFiber === null) { - resultingFirstChild = _newFiber2; - } else { - previousNewFiber.sibling = _newFiber2; - } + var thenable = suspendedThenable; + suspendedThenable = null; - previousNewFiber = _newFiber2; + { + needsToResetSuspendedThenableDEV = false; } - } - if (shouldTrackSideEffects) { - // Any existing children that weren't consumed above were deleted. We need - // to add them to the deletion list. - existingChildren.forEach(function (child) { - return deleteChild(returnFiber, child); - }); + return thenable; } + function checkIfUseWrappedInTryCatch() { + { + // This was set right before SuspenseException was thrown, and it should + // have been cleared when the exception was handled. If it wasn't, + // it must have been caught by userspace. + if (needsToResetSuspendedThenableDEV) { + needsToResetSuspendedThenableDEV = false; + return true; + } + } - return resultingFirstChild; - } + return false; + } + function checkIfUseWrappedInAsyncCatch(rejectedReason) { + // This check runs in prod, too, because it prevents a more confusing + // downstream error, where SuspenseException is caught by a promise and + // thrown asynchronously. + // TODO: Another way to prevent SuspenseException from leaking into an async + // execution context is to check the dispatcher every time `use` is called, + // or some equivalent. That might be preferable for other reasons, too, since + // it matches how we prevent similar mistakes for other hooks. + if (rejectedReason === SuspenseException) { + throw new Error( + "Hooks are not supported inside an async component. This " + + "error is often caused by accidentally adding `'use client'` " + + "to a module that was originally written for the server." + ); + } + } - function reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChildrenIterable, - lanes - ) { - // This is the same implementation as reconcileChildrenArray(), - // but using the iterator instead. - var iteratorFn = getIteratorFn(newChildrenIterable); + var thenableState$1 = null; + var thenableIndexCounter$1 = 0; + var didWarnAboutMaps; + var didWarnAboutGenerators; + var didWarnAboutStringRefs; + var ownerHasKeyUseWarning; + var ownerHasFunctionTypeWarning; - if (typeof iteratorFn !== "function") { - throw new Error( - "An object is not an iterable. This error is likely caused by a bug in " + - "React. Please file an issue." - ); - } + var warnForMissingKey = function (child, returnFiber) {}; { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if ( - typeof Symbol === "function" && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === "Generator" - ) { - if (!didWarnAboutGenerators) { - 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." - ); + didWarnAboutMaps = false; + didWarnAboutGenerators = false; + didWarnAboutStringRefs = {}; + /** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ + + ownerHasKeyUseWarning = {}; + ownerHasFunctionTypeWarning = {}; + + warnForMissingKey = function (child, returnFiber) { + if (child === null || typeof child !== "object") { + return; } - didWarnAboutGenerators = true; - } // Warn about using Maps as children + if (!child._store || child._store.validated || child.key != null) { + return; + } - if (newChildrenIterable.entries === iteratorFn) { - if (!didWarnAboutMaps) { - error( - "Using Maps as children is not supported. " + - "Use an array of keyed ReactElements instead." + if (typeof child._store !== "object") { + 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." ); - } + } // $FlowFixMe[cannot-write] unable to narrow type from mixed to writable object - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. + child._store.validated = true; + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; - var _newChildren = iteratorFn.call(newChildrenIterable); + if (ownerHasKeyUseWarning[componentName]) { + return; + } - if (_newChildren) { - var knownKeys = null; + ownerHasKeyUseWarning[componentName] = true; - var _step = _newChildren.next(); + error( + "Each child in a list should have a unique " + + '"key" prop. See https://reactjs.org/link/warning-keys for ' + + "more information." + ); + }; + } - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); - } - } + function isReactClass(type) { + return type.prototype && type.prototype.isReactComponent; } - var newChildren = iteratorFn.call(newChildrenIterable); + function unwrapThenable(thenable) { + var index = thenableIndexCounter$1; + thenableIndexCounter$1 += 1; + + if (thenableState$1 === null) { + thenableState$1 = createThenableState(); + } - if (newChildren == null) { - throw new Error("An iterable object provided no iterator."); + return trackUsedThenable(thenableState$1, thenable, index); } - var resultingFirstChild = null; - var previousNewFiber = null; - var oldFiber = currentFirstChild; - var lastPlacedIndex = 0; - var newIdx = 0; - var nextOldFiber = null; - var step = newChildren.next(); + function coerceRef(returnFiber, current, element) { + var mixedRef = element.ref; - for ( - ; - oldFiber !== null && !step.done; - newIdx++, step = newChildren.next() - ) { - if (oldFiber.index > newIdx) { - nextOldFiber = oldFiber; - oldFiber = null; - } else { - nextOldFiber = oldFiber.sibling; - } + if ( + mixedRef !== null && + typeof mixedRef !== "function" && + typeof mixedRef !== "object" + ) { + { + if ( + // We warn in ReactElement.js if owner and self are equal for string refs + // because these cannot be automatically converted to an arrow function + // using a codemod. Therefore, we don't have to warn about string refs again. + !( + element._owner && + element._self && + element._owner.stateNode !== element._self + ) && // Will already throw with "Function components cannot have string refs" + !(element._owner && element._owner.tag !== ClassComponent) && // Will already warn with "Function components cannot be given refs" + !( + typeof element.type === "function" && !isReactClass(element.type) + ) && // Will already throw with "Element ref was specified as a string (someStringRef) but no owner was set" + element._owner + ) { + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; - var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); + if (!didWarnAboutStringRefs[componentName]) { + 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 + ); - if (newFiber === null) { - // TODO: This breaks on empty slots like null children. That's - // unfortunate because it triggers the slow path all the time. We need - // a better way to communicate whether this was a miss or null, - // boolean, undefined, etc. - if (oldFiber === null) { - oldFiber = nextOldFiber; + didWarnAboutStringRefs[componentName] = true; + } + } } - break; - } + if (element._owner) { + var owner = element._owner; + var inst; - if (shouldTrackSideEffects) { - if (oldFiber && newFiber.alternate === null) { - // We matched the slot, but we didn't reuse the existing fiber, so we - // need to delete the existing child. - deleteChild(returnFiber, oldFiber); - } - } + if (owner) { + var ownerFiber = owner; - lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + if (ownerFiber.tag !== ClassComponent) { + 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" + ); + } - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = newFiber; - } else { - // TODO: Defer siblings if we're not at the right index for this slot. - // I.e. if we had null values before, then we want to defer this - // for each null value. However, we also don't want to call updateSlot - // with the previous one. - previousNewFiber.sibling = newFiber; + inst = ownerFiber.stateNode; + } + + if (!inst) { + throw new Error( + "Missing owner for string ref " + + mixedRef + + ". This error is likely caused by a " + + "bug in React. Please file an issue." + ); + } // Assigning this to a const so Flow knows it won't change in the closure + + var resolvedInst = inst; + + { + checkPropStringCoercion(mixedRef, "ref"); + } + + var stringRef = "" + mixedRef; // Check if previous string ref matches new string ref + + if ( + current !== null && + current.ref !== null && + typeof current.ref === "function" && + current.ref._stringRef === stringRef + ) { + return current.ref; + } + + var ref = function (value) { + var refs = resolvedInst.refs; + + if (value === null) { + delete refs[stringRef]; + } else { + refs[stringRef] = value; + } + }; + + ref._stringRef = stringRef; + return ref; + } else { + if (typeof mixedRef !== "string") { + throw new Error( + "Expected ref to be a function, a string, an object returned by React.createRef(), or null." + ); + } + + if (!element._owner) { + 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." + ); + } + } } - previousNewFiber = newFiber; - oldFiber = nextOldFiber; + return mixedRef; } - if (step.done) { - // We've reached the end of the new children. We can delete the rest. - deleteRemainingChildren(returnFiber, oldFiber); + function throwOnInvalidObjectType(returnFiber, newChild) { + // $FlowFixMe[method-unbinding] + var childString = Object.prototype.toString.call(newChild); + 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." + ); + } + + function warnOnFunctionType(returnFiber) { + { + var componentName = + getComponentNameFromFiber(returnFiber) || "Component"; + + if (ownerHasFunctionTypeWarning[componentName]) { + return; + } - return resultingFirstChild; + ownerHasFunctionTypeWarning[componentName] = true; + + error( + "Functions are not valid as a React child. This may happen if " + + "you return a Component instead of from render. " + + "Or maybe you meant to call this function rather than return it." + ); + } } - if (oldFiber === null) { - // If we don't have any more existing children we can choose a fast path - // since the rest will all be insertions. - for (; !step.done; newIdx++, step = newChildren.next()) { - var _newFiber3 = createChild(returnFiber, step.value, lanes); + function resolveLazy(lazyType) { + var payload = lazyType._payload; + var init = lazyType._init; + return init(payload); + } // This wrapper function exists because I expect to clone the code in each path + // to be able to optimize each path individually by branching early. This needs + // a compiler or we can do it manually. Helpers that don't need this branching + // live outside of this function. - if (_newFiber3 === null) { - continue; + function createChildReconciler(shouldTrackSideEffects) { + function deleteChild(returnFiber, childToDelete) { + if (!shouldTrackSideEffects) { + // Noop. + return; } - lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); + var deletions = returnFiber.deletions; - if (previousNewFiber === null) { - // TODO: Move out of the loop. This only happens for the first run. - resultingFirstChild = _newFiber3; + if (deletions === null) { + returnFiber.deletions = [childToDelete]; + returnFiber.flags |= ChildDeletion; } else { - previousNewFiber.sibling = _newFiber3; + deletions.push(childToDelete); } - - previousNewFiber = _newFiber3; } - return resultingFirstChild; - } // Add all children to a key map for quick lookups. + function deleteRemainingChildren(returnFiber, currentFirstChild) { + if (!shouldTrackSideEffects) { + // Noop. + return null; + } // TODO: For the shouldClone case, this could be micro-optimized a bit by + // assuming that after the first child we've already added everything. - var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + var childToDelete = currentFirstChild; - for (; !step.done; newIdx++, step = newChildren.next()) { - var _newFiber4 = updateFromMap( - existingChildren, - returnFiber, - newIdx, - step.value, - lanes - ); + while (childToDelete !== null) { + deleteChild(returnFiber, childToDelete); + childToDelete = childToDelete.sibling; + } - if (_newFiber4 !== null) { - if (shouldTrackSideEffects) { - if (_newFiber4.alternate !== null) { - // The new fiber is a work in progress, but if there exists a - // current, that means that we reused the fiber. We need to delete - // it from the child list so that we don't add it to the deletion - // list. - existingChildren.delete( - _newFiber4.key === null ? newIdx : _newFiber4.key - ); + return null; + } + + function mapRemainingChildren(returnFiber, currentFirstChild) { + // Add the remaining children to a temporary map so that we can find them by + // keys quickly. Implicit (null) keys get added to this set with their index + // instead. + var existingChildren = new Map(); + var existingChild = currentFirstChild; + + while (existingChild !== null) { + if (existingChild.key !== null) { + existingChildren.set(existingChild.key, existingChild); + } else { + existingChildren.set(existingChild.index, existingChild); } + + existingChild = existingChild.sibling; } - lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); + return existingChildren; + } + + function useFiber(fiber, pendingProps) { + // We currently set sibling to null and index to 0 here because it is easy + // to forget to do before returning it. E.g. for the single child case. + var clone = createWorkInProgress(fiber, pendingProps); + clone.index = 0; + clone.sibling = null; + return clone; + } + + function placeChild(newFiber, lastPlacedIndex, newIndex) { + newFiber.index = newIndex; + + if (!shouldTrackSideEffects) { + // During hydration, the useId algorithm needs to know which fibers are + // part of a list of children (arrays, iterators). + newFiber.flags |= Forked; + return lastPlacedIndex; + } + + var current = newFiber.alternate; + + if (current !== null) { + var oldIndex = current.index; - if (previousNewFiber === null) { - resultingFirstChild = _newFiber4; + if (oldIndex < lastPlacedIndex) { + // This is a move. + newFiber.flags |= Placement | PlacementDEV; + return lastPlacedIndex; + } else { + // This item can stay in place. + return oldIndex; + } } else { - previousNewFiber.sibling = _newFiber4; + // This is an insertion. + newFiber.flags |= Placement | PlacementDEV; + return lastPlacedIndex; + } + } + + function placeSingleChild(newFiber) { + // This is simpler for the single child case. We only need to do a + // placement for inserting new children. + if (shouldTrackSideEffects && newFiber.alternate === null) { + newFiber.flags |= Placement | PlacementDEV; } - previousNewFiber = _newFiber4; + return newFiber; } - } - if (shouldTrackSideEffects) { - // Any existing children that weren't consumed above were deleted. We need - // to add them to the deletion list. - existingChildren.forEach(function (child) { - return deleteChild(returnFiber, child); - }); - } + function updateTextNode(returnFiber, current, textContent, lanes) { + if (current === null || current.tag !== HostText) { + // Insert + var created = createFiberFromText( + textContent, + returnFiber.mode, + lanes + ); + created.return = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, textContent); + existing.return = returnFiber; + return existing; + } + } - return resultingFirstChild; - } - - function reconcileSingleTextNode( - returnFiber, - currentFirstChild, - textContent, - lanes - ) { - // There's no need to check for keys on text nodes since we don't have a - // way to define them. - if (currentFirstChild !== null && currentFirstChild.tag === HostText) { - // We already have an existing node so let's just update it and delete - // the rest. - deleteRemainingChildren(returnFiber, currentFirstChild.sibling); - var existing = useFiber(currentFirstChild, textContent); - existing.return = returnFiber; - return existing; - } // The existing first child is not a text node so we need to create one - // and delete the existing ones. - - deleteRemainingChildren(returnFiber, currentFirstChild); - var created = createFiberFromText(textContent, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } - - function reconcileSingleElement( - returnFiber, - currentFirstChild, - element, - lanes - ) { - var key = element.key; - var child = currentFirstChild; - - while (child !== null) { - // TODO: If key === null and child.key === null, then this only applies to - // the first item in the list. - if (child.key === key) { + function updateElement(returnFiber, current, element, lanes) { var elementType = element.type; if (elementType === REACT_FRAGMENT_TYPE) { - if (child.tag === Fragment) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, element.props.children); - existing.return = returnFiber; - - { - existing._debugSource = element._source; - existing._debugOwner = element._owner; - } + return updateFragment( + returnFiber, + current, + element.props.children, + lanes, + element.key + ); + } - return existing; - } - } else { + if (current !== null) { if ( - child.elementType === elementType || // Keep this check inline so it only runs on the false path: - isCompatibleFamilyForHotReloading(child, element) || // Lazy types should reconcile their resolved type. + current.elementType === elementType || // Keep this check inline so it only runs on the false path: + isCompatibleFamilyForHotReloading(current, element) || // Lazy types should reconcile their resolved type. // We need to do this after the Hot Reloading check above, // because hot reloading has different semantics than prod because // it doesn't resuspend. So we can't let the call below suspend. (typeof elementType === "object" && elementType !== null && elementType.$$typeof === REACT_LAZY_TYPE && - resolveLazy(elementType) === child.type) + resolveLazy(elementType) === current.type) ) { - deleteRemainingChildren(returnFiber, child.sibling); - - var _existing = useFiber(child, element.props); - - _existing.ref = coerceRef(returnFiber, child, element); - _existing.return = returnFiber; + // Move based on index + var existing = useFiber(current, element.props); + existing.ref = coerceRef(returnFiber, current, element); + existing.return = returnFiber; { - _existing._debugSource = element._source; - _existing._debugOwner = element._owner; + existing._debugSource = element._source; + existing._debugOwner = element._owner; } - return _existing; + return existing; } - } // Didn't match. + } // Insert - deleteRemainingChildren(returnFiber, child); - break; - } else { - deleteChild(returnFiber, child); + var created = createFiberFromElement(element, returnFiber.mode, lanes); + created.ref = coerceRef(returnFiber, current, element); + created.return = returnFiber; + return created; } - child = child.sibling; - } - - if (element.type === REACT_FRAGMENT_TYPE) { - var created = createFiberFromFragment( - element.props.children, - returnFiber.mode, - lanes, - element.key - ); - created.return = returnFiber; - return created; - } else { - var _created4 = createFiberFromElement(element, returnFiber.mode, lanes); - - _created4.ref = coerceRef(returnFiber, currentFirstChild, element); - _created4.return = returnFiber; - return _created4; - } - } - - function reconcileSinglePortal( - returnFiber, - currentFirstChild, - portal, - lanes - ) { - var key = portal.key; - var child = currentFirstChild; - - while (child !== null) { - // TODO: If key === null and child.key === null, then this only applies to - // the first item in the list. - if (child.key === key) { + function updatePortal(returnFiber, current, portal, lanes) { if ( - child.tag === HostPortal && - child.stateNode.containerInfo === portal.containerInfo && - child.stateNode.implementation === portal.implementation + current === null || + current.tag !== HostPortal || + current.stateNode.containerInfo !== portal.containerInfo || + current.stateNode.implementation !== portal.implementation ) { - deleteRemainingChildren(returnFiber, child.sibling); - var existing = useFiber(child, portal.children || []); + // Insert + var created = createFiberFromPortal(portal, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, portal.children || []); existing.return = returnFiber; return existing; - } else { - deleteRemainingChildren(returnFiber, child); - break; } - } else { - deleteChild(returnFiber, child); - } - - child = child.sibling; - } - - var created = createFiberFromPortal(portal, returnFiber.mode, lanes); - created.return = returnFiber; - return created; - } // This API will tag the children with the side-effect of the reconciliation - // itself. They will be added to the side-effect list as we pass through the - // children and the parent. - - function reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - newChild, - lanes - ) { - // This function is not recursive. - // If the top level item is an array, we treat it as a set of children, - // not as a fragment. Nested arrays on the other hand will be treated as - // fragment nodes. Recursion happens at the normal flow. - // Handle top level unkeyed fragments as if they were arrays. - // This leads to an ambiguity between <>{[...]} and <>.... - // We treat the ambiguous cases above the same. - // TODO: Let's use recursion like we do for Usable nodes? - var isUnkeyedTopLevelFragment = - typeof newChild === "object" && - newChild !== null && - newChild.type === REACT_FRAGMENT_TYPE && - newChild.key === null; - - if (isUnkeyedTopLevelFragment) { - newChild = newChild.props.children; - } // Handle object types - - if (typeof newChild === "object" && newChild !== null) { - switch (newChild.$$typeof) { - case REACT_ELEMENT_TYPE: - return placeSingleChild( - reconcileSingleElement( - returnFiber, - currentFirstChild, - newChild, - lanes - ) - ); + } - case REACT_PORTAL_TYPE: - return placeSingleChild( - reconcileSinglePortal( - returnFiber, - currentFirstChild, - newChild, - lanes - ) + function updateFragment(returnFiber, current, fragment, lanes, key) { + if (current === null || current.tag !== Fragment) { + // Insert + var created = createFiberFromFragment( + fragment, + returnFiber.mode, + lanes, + key ); + created.return = returnFiber; + return created; + } else { + // Update + var existing = useFiber(current, fragment); + existing.return = returnFiber; + return existing; + } + } - case REACT_LAZY_TYPE: - var payload = newChild._payload; - var init = newChild._init; // TODO: This function is supposed to be non-recursive. - - return reconcileChildFibers( - returnFiber, - currentFirstChild, - init(payload), + function createChild(returnFiber, newChild, lanes) { + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + var created = createFiberFromText( + "" + newChild, + returnFiber.mode, lanes ); - } + created.return = returnFiber; + return created; + } - if (isArray(newChild)) { - return reconcileChildrenArray( - returnFiber, - currentFirstChild, - newChild, - lanes - ); - } + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _created = createFiberFromElement( + newChild, + returnFiber.mode, + lanes + ); - if (getIteratorFn(newChild)) { - return reconcileChildrenIterator( - returnFiber, - currentFirstChild, - newChild, - lanes - ); - } // Usables are a valid React node type. When React encounters a Usable in - // a child position, it unwraps it using the same algorithm as `use`. For - // example, for promises, React will throw an exception to unwind the - // stack, then replay the component once the promise resolves. - // - // A difference from `use` is that React will keep unwrapping the value - // until it reaches a non-Usable type. - // - // e.g. Usable>> should resolve to T - // - // The structure is a bit unfortunate. Ideally, we shouldn't need to - // replay the entire begin phase of the parent fiber in order to reconcile - // the children again. This would require a somewhat significant refactor, - // because reconcilation happens deep within the begin phase, and - // depending on the type of work, not always at the end. We should - // consider as an future improvement. - - if (typeof newChild.then === "function") { - var thenable = newChild; - return reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - unwrapThenable(thenable), - lanes - ); - } + _created.ref = coerceRef(returnFiber, null, newChild); + _created.return = returnFiber; + return _created; + } - if ( - newChild.$$typeof === REACT_CONTEXT_TYPE || - newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = newChild; - return reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - readContextDuringReconcilation(returnFiber, context, lanes), - lanes - ); - } + case REACT_PORTAL_TYPE: { + var _created2 = createFiberFromPortal( + newChild, + returnFiber.mode, + lanes + ); - throwOnInvalidObjectType(returnFiber, newChild); - } + _created2.return = returnFiber; + return _created2; + } - if ( - (typeof newChild === "string" && newChild !== "") || - typeof newChild === "number" - ) { - return placeSingleChild( - reconcileSingleTextNode( - returnFiber, - currentFirstChild, - "" + newChild, - lanes - ) - ); - } + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return createChild(returnFiber, init(payload), lanes); + } + } - { - if (typeof newChild === "function") { - warnOnFunctionType(returnFiber); - } - } // Remaining cases are all treated as empty. - - return deleteRemainingChildren(returnFiber, currentFirstChild); - } - - function reconcileChildFibers( - returnFiber, - currentFirstChild, - newChild, - lanes - ) { - // This indirection only exists so we can reset `thenableState` at the end. - // It should get inlined by Closure. - thenableIndexCounter$1 = 0; - var firstChildFiber = reconcileChildFibersImpl( - returnFiber, - currentFirstChild, - newChild, - lanes - ); - thenableState$1 = null; // Don't bother to reset `thenableIndexCounter` to 0 because it always gets - // set at the beginning. + if (isArray(newChild) || getIteratorFn(newChild)) { + var _created3 = createFiberFromFragment( + newChild, + returnFiber.mode, + lanes, + null + ); - return firstChildFiber; - } + _created3.return = returnFiber; + return _created3; + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. - return reconcileChildFibers; -} + if (typeof newChild.then === "function") { + var thenable = newChild; + return createChild(returnFiber, unwrapThenable(thenable), lanes); + } -var reconcileChildFibers = createChildReconciler(true); -var mountChildFibers = createChildReconciler(false); -function resetChildReconcilerOnUnwind() { - // On unwind, clear any pending thenables that were used. - thenableState$1 = null; - thenableIndexCounter$1 = 0; -} -function cloneChildFibers(current, workInProgress) { - if (current !== null && workInProgress.child !== current.child) { - throw new Error("Resuming work not yet implemented."); - } - - if (workInProgress.child === null) { - return; - } - - var currentChild = workInProgress.child; - var newChild = createWorkInProgress(currentChild, currentChild.pendingProps); - workInProgress.child = newChild; - newChild.return = workInProgress; - - while (currentChild.sibling !== null) { - currentChild = currentChild.sibling; - newChild = newChild.sibling = createWorkInProgress( - currentChild, - currentChild.pendingProps - ); - newChild.return = workInProgress; - } + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return createChild( + returnFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } - newChild.sibling = null; -} // Reset a workInProgress child set to prepare it for a second pass. + throwOnInvalidObjectType(returnFiber, newChild); + } -function resetChildFibers(workInProgress, lanes) { - var child = workInProgress.child; + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } - while (child !== null) { - resetWorkInProgress(child, lanes); - child = child.sibling; - } -} + return null; + } -// TODO: This isn't being used yet, but it's intended to replace the -// InvisibleParentContext that is currently managed by SuspenseContext. - -var currentTreeHiddenStackCursor = createCursor(null); -var prevEntangledRenderLanesCursor = createCursor(NoLanes); -function pushHiddenContext(fiber, context) { - var prevEntangledRenderLanes = getEntangledRenderLanes(); - push(prevEntangledRenderLanesCursor, prevEntangledRenderLanes, fiber); - push(currentTreeHiddenStackCursor, context, fiber); // When rendering a subtree that's currently hidden, we must include all - // lanes that would have rendered if the hidden subtree hadn't been deferred. - // That is, in order to reveal content from hidden -> visible, we must commit - // all the updates that we skipped when we originally hid the tree. - - setEntangledRenderLanes( - mergeLanes(prevEntangledRenderLanes, context.baseLanes) - ); -} -function reuseHiddenContextOnStack(fiber) { - // This subtree is not currently hidden, so we don't need to add any lanes - // to the render lanes. But we still need to push something to avoid a - // context mismatch. Reuse the existing context on the stack. - push(prevEntangledRenderLanesCursor, getEntangledRenderLanes(), fiber); - push( - currentTreeHiddenStackCursor, - currentTreeHiddenStackCursor.current, - fiber - ); -} -function popHiddenContext(fiber) { - // Restore the previous render lanes from the stack - setEntangledRenderLanes(prevEntangledRenderLanesCursor.current); - pop(currentTreeHiddenStackCursor, fiber); - pop(prevEntangledRenderLanesCursor, fiber); -} -function isCurrentTreeHidden() { - return currentTreeHiddenStackCursor.current !== null; -} + function updateSlot(returnFiber, oldFiber, newChild, lanes) { + // Update the fiber if the keys match, otherwise return null. + var key = oldFiber !== null ? oldFiber.key : null; -// suspends, i.e. it's the nearest `catch` block on the stack. - -var suspenseHandlerStackCursor = createCursor(null); // Represents the outermost boundary that is not visible in the current tree. -// Everything above this is the "shell". When this is null, it means we're -// rendering in the shell of the app. If it's non-null, it means we're rendering -// deeper than the shell, inside a new tree that wasn't already visible. -// -// The main way we use this concept is to determine whether showing a fallback -// would result in a desirable or undesirable loading state. Activing a fallback -// in the shell is considered an undersirable loading state, because it would -// mean hiding visible (albeit stale) content in the current tree — we prefer to -// show the stale content, rather than switch to a fallback. But showing a -// fallback in a new tree is fine, because there's no stale content to -// prefer instead. - -var shellBoundary = null; -function getShellBoundary() { - return shellBoundary; -} -function pushPrimaryTreeSuspenseHandler(handler) { - // TODO: Pass as argument - var current = handler.alternate; - var props = handler.pendingProps; // Shallow Suspense context fields, like ForceSuspenseFallback, should only be - // propagated a single level. For example, when ForceSuspenseFallback is set, - // it should only force the nearest Suspense boundary into fallback mode. - - pushSuspenseListContext( - handler, - setDefaultShallowSuspenseListContext(suspenseStackCursor.current) - ); // Experimental feature: Some Suspense boundaries are marked as having an - // undesirable fallback state. These have special behavior where we only - // activate the fallback if there's no other boundary on the stack that we can - // use instead. - - if ( - props.unstable_avoidThisFallback === true && // If an avoided boundary is already visible, it behaves identically to - // a regular Suspense boundary. - (current === null || isCurrentTreeHidden()) - ) { - if (shellBoundary === null) { - // We're rendering in the shell. There's no parent Suspense boundary that - // can provide a desirable fallback state. We'll use this boundary. - push(suspenseHandlerStackCursor, handler, handler); // However, because this is not a desirable fallback, the children are - // still considered part of the shell. So we intentionally don't assign - // to `shellBoundary`. - } else { - // There's already a parent Suspense boundary that can provide a desirable - // fallback state. Prefer that one. - var handlerOnStack = suspenseHandlerStackCursor.current; - push(suspenseHandlerStackCursor, handlerOnStack, handler); - } + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + if (key !== null) { + return null; + } - return; - } // TODO: If the parent Suspense handler already suspended, there's no reason - // to push a nested Suspense handler, because it will get replaced by the - // outer fallback, anyway. Consider this as a future optimization. + return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); + } - push(suspenseHandlerStackCursor, handler, handler); + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + if (newChild.key === key) { + return updateElement(returnFiber, oldFiber, newChild, lanes); + } else { + return null; + } + } - if (shellBoundary === null) { - if (current === null || isCurrentTreeHidden()) { - // This boundary is not visible in the current UI. - shellBoundary = handler; - } else { - var prevState = current.memoizedState; + case REACT_PORTAL_TYPE: { + if (newChild.key === key) { + return updatePortal(returnFiber, oldFiber, newChild, lanes); + } else { + return null; + } + } - if (prevState !== null) { - // This boundary is showing a fallback in the current UI. - shellBoundary = handler; - } - } - } -} -function pushFallbackTreeSuspenseHandler(fiber) { - // We're about to render the fallback. If something in the fallback suspends, - // it's akin to throwing inside of a `catch` block. This boundary should not - // capture. Reuse the existing handler on the stack. - reuseSuspenseHandlerOnStack(fiber); -} -function pushOffscreenSuspenseHandler(fiber) { - if (fiber.tag === OffscreenComponent) { - // A SuspenseList context is only pushed here to avoid a push/pop mismatch. - // Reuse the current value on the stack. - // TODO: We can avoid needing to push here by by forking popSuspenseHandler - // into separate functions for Suspense and Offscreen. - pushSuspenseListContext(fiber, suspenseStackCursor.current); - push(suspenseHandlerStackCursor, fiber, fiber); - - if (shellBoundary !== null); - else { - var current = fiber.alternate; + case REACT_LAZY_TYPE: { + var payload = newChild._payload; + var init = newChild._init; + return updateSlot(returnFiber, oldFiber, init(payload), lanes); + } + } - if (current !== null) { - var prevState = current.memoizedState; + if (isArray(newChild) || getIteratorFn(newChild)) { + if (key !== null) { + return null; + } - if (prevState !== null) { - // This is the first boundary in the stack that's already showing - // a fallback. So everything outside is considered the shell. - shellBoundary = fiber; - } - } - } - } else { - // This is a LegacyHidden component. - reuseSuspenseHandlerOnStack(fiber); - } -} -function reuseSuspenseHandlerOnStack(fiber) { - pushSuspenseListContext(fiber, suspenseStackCursor.current); - push(suspenseHandlerStackCursor, getSuspenseHandler(), fiber); -} -function getSuspenseHandler() { - return suspenseHandlerStackCursor.current; -} -function popSuspenseHandler(fiber) { - pop(suspenseHandlerStackCursor, fiber); - - if (shellBoundary === fiber) { - // Popping back into the shell. - shellBoundary = null; - } - - popSuspenseListContext(fiber); -} // SuspenseList context -// TODO: Move to a separate module? We may change the SuspenseList -// implementation to hide/show in the commit phase, anyway. - -var DefaultSuspenseContext = 0; -var SubtreeSuspenseContextMask = 1; // ForceSuspenseFallback can be used by SuspenseList to force newly added -// items into their fallback state during one of the render passes. - -var ForceSuspenseFallback = 2; -var suspenseStackCursor = createCursor(DefaultSuspenseContext); -function hasSuspenseListContext(parentContext, flag) { - return (parentContext & flag) !== 0; -} -function setDefaultShallowSuspenseListContext(parentContext) { - return parentContext & SubtreeSuspenseContextMask; -} -function setShallowSuspenseListContext(parentContext, shallowContext) { - return (parentContext & SubtreeSuspenseContextMask) | shallowContext; -} -function pushSuspenseListContext(fiber, newContext) { - push(suspenseStackCursor, newContext, fiber); -} -function popSuspenseListContext(fiber) { - pop(suspenseStackCursor, fiber); -} + return updateFragment(returnFiber, oldFiber, newChild, lanes, null); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. -// A non-null SuspenseState means that it is blocked for one reason or another. -// - A non-null dehydrated field means it's blocked pending hydration. -// - A non-null dehydrated field can use isSuspenseInstancePending or -// isSuspenseInstanceFallback to query the reason for being dehydrated. -// - A null dehydrated field means it's blocked by something suspending and -// we're currently showing a fallback instead. + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateSlot( + returnFiber, + oldFiber, + unwrapThenable(thenable), + lanes + ); + } + + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateSlot( + returnFiber, + oldFiber, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } -function findFirstSuspended(row) { - var node = row; + throwOnInvalidObjectType(returnFiber, newChild); + } - while (node !== null) { - if (node.tag === SuspenseComponent) { - var state = node.memoizedState; + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } - if (state !== null) { - var dehydrated = state.dehydrated; + return null; + } + function updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChild, + lanes + ) { if ( - dehydrated === null || - isSuspenseInstancePending() || - isSuspenseInstanceFallback() + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" ) { - return node; + // Text nodes don't have keys, so we neither have to check the old nor + // new node for the key. If both are text nodes, they match. + var matchedFiber = existingChildren.get(newIdx) || null; + return updateTextNode( + returnFiber, + matchedFiber, + "" + newChild, + lanes + ); } - } - } else if ( - node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't - // keep track of whether it suspended or not. - node.memoizedProps.revealOrder !== undefined - ) { - var didSuspend = (node.flags & DidCapture) !== NoFlags$1; - if (didSuspend) { - return node; - } - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _matchedFiber = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; - if (node === row) { - return null; - } + return updateElement(returnFiber, _matchedFiber, newChild, lanes); + } + + case REACT_PORTAL_TYPE: { + var _matchedFiber2 = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null; + + return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); + } + + case REACT_LAZY_TYPE: + var payload = newChild._payload; + var init = newChild._init; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + init(payload), + lanes + ); + } + + if (isArray(newChild) || getIteratorFn(newChild)) { + var _matchedFiber3 = existingChildren.get(newIdx) || null; + + return updateFragment( + returnFiber, + _matchedFiber3, + newChild, + lanes, + null + ); + } // Usable node types + // + // Unwrap the inner value and recursively call this function again. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + unwrapThenable(thenable), + lanes + ); + } + + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return updateFromMap( + existingChildren, + returnFiber, + newIdx, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } + + throwOnInvalidObjectType(returnFiber, newChild); + } + + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } - while (node.sibling === null) { - if (node.return === null || node.return === row) { return null; } + /** + * Warns if there is a duplicate or missing key + */ - node = node.return; - } + function warnOnInvalidKey(child, knownKeys, returnFiber) { + { + if (typeof child !== "object" || child === null) { + return knownKeys; + } - node.sibling.return = node.return; - node = node.sibling; - } + switch (child.$$typeof) { + case REACT_ELEMENT_TYPE: + case REACT_PORTAL_TYPE: + warnForMissingKey(child, returnFiber); + var key = child.key; - return null; -} + if (typeof key !== "string") { + break; + } -var NoFlags = - /* */ - 0; // Represents whether effect should fire. - -var HasEffect = - /* */ - 1; // Represents the phase in which the effect (not the clean-up) fires. - -var Insertion = - /* */ - 2; -var Layout = - /* */ - 4; -var Passive = - /* */ - 8; - -var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // A linked list of all the roots with pending work. In an idiomatic app, -// there's only a single root, but we do support multi root apps, hence this -// extra complexity. But this module is optimized for the single root case. - -var firstScheduledRoot = null; -var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. - -var didScheduleMicrotask = false; // `act` "microtasks" are scheduled on the `act` queue instead of an actual -// microtask, so we have to dedupe those separately. This wouldn't be an issue -// if we required all `act` calls to be awaited, which we might in the future. - -var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. - -var mightHavePendingSyncWork = false; -var isFlushingWork = false; -var currentEventTransitionLane = NoLane; -function ensureRootIsScheduled(root) { - // This function is called whenever a root receives an update. It does two - // things 1) it ensures the root is in the root schedule, and 2) it ensures - // there's a pending microtask to process the root schedule. - // - // Most of the actual scheduling logic does not happen until - // `scheduleTaskForRootDuringMicrotask` runs. - // Add the root to the schedule - if (root === lastScheduledRoot || root.next !== null); - else { - if (lastScheduledRoot === null) { - firstScheduledRoot = lastScheduledRoot = root; - } else { - lastScheduledRoot.next = root; - lastScheduledRoot = root; - } - } // Any time a root received an update, we set this to true until the next time - // we process the schedule. If it's false, then we can quickly exit flushSync - // without consulting the schedule. - - mightHavePendingSyncWork = true; // At the end of the current event, go through each of the roots and ensure - // there's a task scheduled for each one at the correct priority. - - if (ReactCurrentActQueue$2.current !== null) { - // We're inside an `act` scope. - if (!didScheduleMicrotask_act) { - didScheduleMicrotask_act = true; - scheduleImmediateTask(processRootScheduleInMicrotask); - } - } else { - if (!didScheduleMicrotask) { - didScheduleMicrotask = true; - scheduleImmediateTask(processRootScheduleInMicrotask); - } - } - - if (!enableDeferRootSchedulingToMicrotask) { - // While this flag is disabled, we schedule the render task immediately - // instead of waiting a microtask. - // TODO: We need to land enableDeferRootSchedulingToMicrotask ASAP to - // unblock additional features we have planned. - scheduleTaskForRootDuringMicrotask(root, now$1()); - } - - if (ReactCurrentActQueue$2.isBatchingLegacy && root.tag === LegacyRoot) { - // Special `act` case: Record whenever a legacy update is scheduled. - ReactCurrentActQueue$2.didScheduleLegacyUpdate = true; - } -} -function flushSyncWorkOnAllRoots() { - // This is allowed to be called synchronously, but the caller should check - // the execution context first. - flushSyncWorkAcrossRoots_impl(false); -} -function flushSyncWorkOnLegacyRootsOnly() { - // This is allowed to be called synchronously, but the caller should check - // the execution context first. - flushSyncWorkAcrossRoots_impl(true); -} + if (knownKeys === null) { + knownKeys = new Set(); + knownKeys.add(key); + break; + } -function flushSyncWorkAcrossRoots_impl(onlyLegacy) { - if (isFlushingWork) { - // Prevent reentrancy. - // TODO: Is this overly defensive? The callers must check the execution - // context first regardless. - return; - } - - if (!mightHavePendingSyncWork) { - // Fast path. There's no sync work to do. - return; - } // There may or may not be synchronous work scheduled. Let's check. - - var didPerformSomeWork; - var errors = null; - isFlushingWork = true; - - do { - didPerformSomeWork = false; - var root = firstScheduledRoot; - - while (root !== null) { - if (onlyLegacy && root.tag !== LegacyRoot); - else { - var workInProgressRoot = getWorkInProgressRoot(); - var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); - var nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes - ); + if (!knownKeys.has(key)) { + knownKeys.add(key); + break; + } - if (includesSyncLane(nextLanes)) { - // This root has pending sync work. Flush it now. - try { - didPerformSomeWork = true; - performSyncWorkOnRoot(root, nextLanes); - } catch (error) { - // Collect errors so we can rethrow them at the end - if (errors === null) { - errors = [error]; - } else { - errors.push(error); - } + 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 + ); + + break; + + case REACT_LAZY_TYPE: + var payload = child._payload; + var init = child._init; + warnOnInvalidKey(init(payload), knownKeys, returnFiber); + break; } } + + return knownKeys; } - root = root.next; - } - } while (didPerformSomeWork); + function reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChildren, + lanes + ) { + // This algorithm can't optimize by searching from both ends since we + // don't have backpointers on fibers. I'm trying to see how far we can get + // with that model. If it ends up not being worth the tradeoffs, we can + // add it later. + // Even with a two ended optimization, we'd want to optimize for the case + // where there are few changes and brute force the comparison instead of + // going for the Map. It'd like to explore hitting that path first in + // forward-only mode and only go for the Map once we notice that we need + // lots of look ahead. This doesn't handle reversal as well as two ended + // search but that's unusual. Besides, for the two ended optimization to + // work on Iterables, we'd need to copy the whole set. + // In this first iteration, we'll just live with hitting the bad case + // (adding everything to a Map) in for every insert/move. + // If you change this code, also update reconcileChildrenIterator() which + // uses the same algorithm. + { + // First, validate keys. + var knownKeys = null; + + for (var i = 0; i < newChildren.length; i++) { + var child = newChildren[i]; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + } + } - isFlushingWork = false; // If any errors were thrown, rethrow them right before exiting. - // TODO: Consider returning these to the caller, to allow them to decide - // how/when to rethrow. + var resultingFirstChild = null; + var previousNewFiber = null; + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; - if (errors !== null) { - if (errors.length > 1) { - if (typeof AggregateError === "function") { - // eslint-disable-next-line no-undef - throw new AggregateError(errors); - } else { - for (var i = 1; i < errors.length; i++) { - scheduleImmediateTask(throwError.bind(null, errors[i])); + for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } + + var newFiber = updateSlot( + returnFiber, + oldFiber, + newChildren[newIdx], + lanes + ); + + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (oldFiber === null) { + oldFiber = nextOldFiber; + } + + break; + } + + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); + } + } + + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber; + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber; + } + + previousNewFiber = newFiber; + oldFiber = nextOldFiber; } - var firstError = errors[0]; - throw firstError; - } - } else { - var error = errors[0]; - throw error; - } - } -} + if (newIdx === newChildren.length) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); -function throwError(error) { - throw error; -} + return resultingFirstChild; + } + + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber = createChild( + returnFiber, + newChildren[newIdx], + lanes + ); + + if (_newFiber === null) { + continue; + } + + lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); -function processRootScheduleInMicrotask() { - // This function is always called inside a microtask. It should never be - // called synchronously. - didScheduleMicrotask = false; + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber; + } else { + previousNewFiber.sibling = _newFiber; + } - { - didScheduleMicrotask_act = false; - } // We'll recompute this as we iterate through all the roots and schedule them. + previousNewFiber = _newFiber; + } - mightHavePendingSyncWork = false; - var currentTime = now$1(); - var prev = null; - var root = firstScheduledRoot; + return resultingFirstChild; + } // Add all children to a key map for quick lookups. - while (root !== null) { - var next = root.next; + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. - if ( - currentEventTransitionLane !== NoLane && - shouldAttemptEagerTransition() - ) { - // A transition was scheduled during an event, but we're going to try to - // render it synchronously anyway. We do this during a popstate event to - // preserve the scroll position of the previous page. - upgradePendingLaneToSync(root, currentEventTransitionLane); - } + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber2 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChildren[newIdx], + lanes + ); + + if (_newFiber2 !== null) { + if (shouldTrackSideEffects) { + if (_newFiber2.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren.delete( + _newFiber2.key === null ? newIdx : _newFiber2.key + ); + } + } + + lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + resultingFirstChild = _newFiber2; + } else { + previousNewFiber.sibling = _newFiber2; + } + + previousNewFiber = _newFiber2; + } + } + + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function (child) { + return deleteChild(returnFiber, child); + }); + } + + return resultingFirstChild; + } + + function reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChildrenIterable, + lanes + ) { + // This is the same implementation as reconcileChildrenArray(), + // but using the iterator instead. + var iteratorFn = getIteratorFn(newChildrenIterable); + + if (typeof iteratorFn !== "function") { + throw new Error( + "An object is not an iterable. This error is likely caused by a bug in " + + "React. Please file an issue." + ); + } + + { + // We don't support rendering Generators because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + if ( + typeof Symbol === "function" && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag + newChildrenIterable[Symbol.toStringTag] === "Generator" + ) { + if (!didWarnAboutGenerators) { + 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." + ); + } - var nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); + didWarnAboutGenerators = true; + } // Warn about using Maps as children + + if (newChildrenIterable.entries === iteratorFn) { + if (!didWarnAboutMaps) { + error( + "Using Maps as children is not supported. " + + "Use an array of keyed ReactElements instead." + ); + } + + didWarnAboutMaps = true; + } // First, validate keys. + // We'll get a different iterator later for the main pass. + + var _newChildren = iteratorFn.call(newChildrenIterable); + + if (_newChildren) { + var knownKeys = null; + + var _step = _newChildren.next(); + + for (; !_step.done; _step = _newChildren.next()) { + var child = _step.value; + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + } + } + } + + var newChildren = iteratorFn.call(newChildrenIterable); + + if (newChildren == null) { + throw new Error("An iterable object provided no iterator."); + } + + var resultingFirstChild = null; + var previousNewFiber = null; + var oldFiber = currentFirstChild; + var lastPlacedIndex = 0; + var newIdx = 0; + var nextOldFiber = null; + var step = newChildren.next(); + + for ( + ; + oldFiber !== null && !step.done; + newIdx++, step = newChildren.next() + ) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber; + oldFiber = null; + } else { + nextOldFiber = oldFiber.sibling; + } + + var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); + + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (oldFiber === null) { + oldFiber = nextOldFiber; + } + + break; + } + + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber); + } + } + + lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber; + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber; + } + + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } + + if (step.done) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber); + + return resultingFirstChild; + } + + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber3 = createChild(returnFiber, step.value, lanes); + + if (_newFiber3 === null) { + continue; + } + + lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber3; + } else { + previousNewFiber.sibling = _newFiber3; + } + + previousNewFiber = _newFiber3; + } + + return resultingFirstChild; + } // Add all children to a key map for quick lookups. + + var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. + + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber4 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + step.value, + lanes + ); + + if (_newFiber4 !== null) { + if (shouldTrackSideEffects) { + if (_newFiber4.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren.delete( + _newFiber4.key === null ? newIdx : _newFiber4.key + ); + } + } + + lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); + + if (previousNewFiber === null) { + resultingFirstChild = _newFiber4; + } else { + previousNewFiber.sibling = _newFiber4; + } + + previousNewFiber = _newFiber4; + } + } + + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function (child) { + return deleteChild(returnFiber, child); + }); + } + + return resultingFirstChild; + } + + function reconcileSingleTextNode( + returnFiber, + currentFirstChild, + textContent, + lanes + ) { + // There's no need to check for keys on text nodes since we don't have a + // way to define them. + if (currentFirstChild !== null && currentFirstChild.tag === HostText) { + // We already have an existing node so let's just update it and delete + // the rest. + deleteRemainingChildren(returnFiber, currentFirstChild.sibling); + var existing = useFiber(currentFirstChild, textContent); + existing.return = returnFiber; + return existing; + } // The existing first child is not a text node so we need to create one + // and delete the existing ones. + + deleteRemainingChildren(returnFiber, currentFirstChild); + var created = createFiberFromText(textContent, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } + + function reconcileSingleElement( + returnFiber, + currentFirstChild, + element, + lanes + ) { + var key = element.key; + var child = currentFirstChild; + + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + var elementType = element.type; + + if (elementType === REACT_FRAGMENT_TYPE) { + if (child.tag === Fragment) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, element.props.children); + existing.return = returnFiber; + + { + existing._debugSource = element._source; + existing._debugOwner = element._owner; + } + + return existing; + } + } else { + if ( + child.elementType === elementType || // Keep this check inline so it only runs on the false path: + isCompatibleFamilyForHotReloading(child, element) || // Lazy types should reconcile their resolved type. + // We need to do this after the Hot Reloading check above, + // because hot reloading has different semantics than prod because + // it doesn't resuspend. So we can't let the call below suspend. + (typeof elementType === "object" && + elementType !== null && + elementType.$$typeof === REACT_LAZY_TYPE && + resolveLazy(elementType) === child.type) + ) { + deleteRemainingChildren(returnFiber, child.sibling); + + var _existing = useFiber(child, element.props); + + _existing.ref = coerceRef(returnFiber, child, element); + _existing.return = returnFiber; + + { + _existing._debugSource = element._source; + _existing._debugOwner = element._owner; + } + + return _existing; + } + } // Didn't match. + + deleteRemainingChildren(returnFiber, child); + break; + } else { + deleteChild(returnFiber, child); + } + + child = child.sibling; + } + + if (element.type === REACT_FRAGMENT_TYPE) { + var created = createFiberFromFragment( + element.props.children, + returnFiber.mode, + lanes, + element.key + ); + created.return = returnFiber; + return created; + } else { + var _created4 = createFiberFromElement( + element, + returnFiber.mode, + lanes + ); + + _created4.ref = coerceRef(returnFiber, currentFirstChild, element); + _created4.return = returnFiber; + return _created4; + } + } + + function reconcileSinglePortal( + returnFiber, + currentFirstChild, + portal, + lanes + ) { + var key = portal.key; + var child = currentFirstChild; + + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + if ( + child.tag === HostPortal && + child.stateNode.containerInfo === portal.containerInfo && + child.stateNode.implementation === portal.implementation + ) { + deleteRemainingChildren(returnFiber, child.sibling); + var existing = useFiber(child, portal.children || []); + existing.return = returnFiber; + return existing; + } else { + deleteRemainingChildren(returnFiber, child); + break; + } + } else { + deleteChild(returnFiber, child); + } + + child = child.sibling; + } + + var created = createFiberFromPortal(portal, returnFiber.mode, lanes); + created.return = returnFiber; + return created; + } // This API will tag the children with the side-effect of the reconciliation + // itself. They will be added to the side-effect list as we pass through the + // children and the parent. + + function reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + // This function is not recursive. + // If the top level item is an array, we treat it as a set of children, + // not as a fragment. Nested arrays on the other hand will be treated as + // fragment nodes. Recursion happens at the normal flow. + // Handle top level unkeyed fragments as if they were arrays. + // This leads to an ambiguity between <>{[...]} and <>.... + // We treat the ambiguous cases above the same. + // TODO: Let's use recursion like we do for Usable nodes? + var isUnkeyedTopLevelFragment = + typeof newChild === "object" && + newChild !== null && + newChild.type === REACT_FRAGMENT_TYPE && + newChild.key === null; + + if (isUnkeyedTopLevelFragment) { + newChild = newChild.props.children; + } // Handle object types + + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + return placeSingleChild( + reconcileSingleElement( + returnFiber, + currentFirstChild, + newChild, + lanes + ) + ); + + case REACT_PORTAL_TYPE: + return placeSingleChild( + reconcileSinglePortal( + returnFiber, + currentFirstChild, + newChild, + lanes + ) + ); + + case REACT_LAZY_TYPE: + var payload = newChild._payload; + var init = newChild._init; // TODO: This function is supposed to be non-recursive. + + return reconcileChildFibers( + returnFiber, + currentFirstChild, + init(payload), + lanes + ); + } + + if (isArray(newChild)) { + return reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + } + + if (getIteratorFn(newChild)) { + return reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + } // Usables are a valid React node type. When React encounters a Usable in + // a child position, it unwraps it using the same algorithm as `use`. For + // example, for promises, React will throw an exception to unwind the + // stack, then replay the component once the promise resolves. + // + // A difference from `use` is that React will keep unwrapping the value + // until it reaches a non-Usable type. + // + // e.g. Usable>> should resolve to T + // + // The structure is a bit unfortunate. Ideally, we shouldn't need to + // replay the entire begin phase of the parent fiber in order to reconcile + // the children again. This would require a somewhat significant refactor, + // because reconcilation happens deep within the begin phase, and + // depending on the type of work, not always at the end. We should + // consider as an future improvement. + + if (typeof newChild.then === "function") { + var thenable = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + unwrapThenable(thenable), + lanes + ); + } + + if ( + newChild.$$typeof === REACT_CONTEXT_TYPE || + newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = newChild; + return reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + readContextDuringReconcilation(returnFiber, context, lanes), + lanes + ); + } + + throwOnInvalidObjectType(returnFiber, newChild); + } + + if ( + (typeof newChild === "string" && newChild !== "") || + typeof newChild === "number" + ) { + return placeSingleChild( + reconcileSingleTextNode( + returnFiber, + currentFirstChild, + "" + newChild, + lanes + ) + ); + } + + { + if (typeof newChild === "function") { + warnOnFunctionType(returnFiber); + } + } // Remaining cases are all treated as empty. + + return deleteRemainingChildren(returnFiber, currentFirstChild); + } + + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + lanes + ) { + // This indirection only exists so we can reset `thenableState` at the end. + // It should get inlined by Closure. + thenableIndexCounter$1 = 0; + var firstChildFiber = reconcileChildFibersImpl( + returnFiber, + currentFirstChild, + newChild, + lanes + ); + thenableState$1 = null; // Don't bother to reset `thenableIndexCounter` to 0 because it always gets + // set at the beginning. + + return firstChildFiber; + } + + return reconcileChildFibers; + } + + var reconcileChildFibers = createChildReconciler(true); + var mountChildFibers = createChildReconciler(false); + function resetChildReconcilerOnUnwind() { + // On unwind, clear any pending thenables that were used. + thenableState$1 = null; + thenableIndexCounter$1 = 0; + } + function cloneChildFibers(current, workInProgress) { + if (current !== null && workInProgress.child !== current.child) { + throw new Error("Resuming work not yet implemented."); + } + + if (workInProgress.child === null) { + return; + } + + var currentChild = workInProgress.child; + var newChild = createWorkInProgress( + currentChild, + currentChild.pendingProps + ); + workInProgress.child = newChild; + newChild.return = workInProgress; + + while (currentChild.sibling !== null) { + currentChild = currentChild.sibling; + newChild = newChild.sibling = createWorkInProgress( + currentChild, + currentChild.pendingProps + ); + newChild.return = workInProgress; + } + + newChild.sibling = null; + } // Reset a workInProgress child set to prepare it for a second pass. + + function resetChildFibers(workInProgress, lanes) { + var child = workInProgress.child; + + while (child !== null) { + resetWorkInProgress(child, lanes); + child = child.sibling; + } + } + + // TODO: This isn't being used yet, but it's intended to replace the + // InvisibleParentContext that is currently managed by SuspenseContext. + + var currentTreeHiddenStackCursor = createCursor(null); + var prevEntangledRenderLanesCursor = createCursor(NoLanes); + function pushHiddenContext(fiber, context) { + var prevEntangledRenderLanes = getEntangledRenderLanes(); + push(prevEntangledRenderLanesCursor, prevEntangledRenderLanes, fiber); + push(currentTreeHiddenStackCursor, context, fiber); // When rendering a subtree that's currently hidden, we must include all + // lanes that would have rendered if the hidden subtree hadn't been deferred. + // That is, in order to reveal content from hidden -> visible, we must commit + // all the updates that we skipped when we originally hid the tree. + + setEntangledRenderLanes( + mergeLanes(prevEntangledRenderLanes, context.baseLanes) + ); + } + function reuseHiddenContextOnStack(fiber) { + // This subtree is not currently hidden, so we don't need to add any lanes + // to the render lanes. But we still need to push something to avoid a + // context mismatch. Reuse the existing context on the stack. + push(prevEntangledRenderLanesCursor, getEntangledRenderLanes(), fiber); + push( + currentTreeHiddenStackCursor, + currentTreeHiddenStackCursor.current, + fiber + ); + } + function popHiddenContext(fiber) { + // Restore the previous render lanes from the stack + setEntangledRenderLanes(prevEntangledRenderLanesCursor.current); + pop(currentTreeHiddenStackCursor, fiber); + pop(prevEntangledRenderLanesCursor, fiber); + } + function isCurrentTreeHidden() { + return currentTreeHiddenStackCursor.current !== null; + } + + // suspends, i.e. it's the nearest `catch` block on the stack. + + var suspenseHandlerStackCursor = createCursor(null); // Represents the outermost boundary that is not visible in the current tree. + // Everything above this is the "shell". When this is null, it means we're + // rendering in the shell of the app. If it's non-null, it means we're rendering + // deeper than the shell, inside a new tree that wasn't already visible. + // + // The main way we use this concept is to determine whether showing a fallback + // would result in a desirable or undesirable loading state. Activing a fallback + // in the shell is considered an undersirable loading state, because it would + // mean hiding visible (albeit stale) content in the current tree — we prefer to + // show the stale content, rather than switch to a fallback. But showing a + // fallback in a new tree is fine, because there's no stale content to + // prefer instead. + + var shellBoundary = null; + function getShellBoundary() { + return shellBoundary; + } + function pushPrimaryTreeSuspenseHandler(handler) { + // TODO: Pass as argument + var current = handler.alternate; + var props = handler.pendingProps; // Shallow Suspense context fields, like ForceSuspenseFallback, should only be + // propagated a single level. For example, when ForceSuspenseFallback is set, + // it should only force the nearest Suspense boundary into fallback mode. + + pushSuspenseListContext( + handler, + setDefaultShallowSuspenseListContext(suspenseStackCursor.current) + ); // Experimental feature: Some Suspense boundaries are marked as having an + // undesirable fallback state. These have special behavior where we only + // activate the fallback if there's no other boundary on the stack that we can + // use instead. + + if ( + props.unstable_avoidThisFallback === true && // If an avoided boundary is already visible, it behaves identically to + // a regular Suspense boundary. + (current === null || isCurrentTreeHidden()) + ) { + if (shellBoundary === null) { + // We're rendering in the shell. There's no parent Suspense boundary that + // can provide a desirable fallback state. We'll use this boundary. + push(suspenseHandlerStackCursor, handler, handler); // However, because this is not a desirable fallback, the children are + // still considered part of the shell. So we intentionally don't assign + // to `shellBoundary`. + } else { + // There's already a parent Suspense boundary that can provide a desirable + // fallback state. Prefer that one. + var handlerOnStack = suspenseHandlerStackCursor.current; + push(suspenseHandlerStackCursor, handlerOnStack, handler); + } + + return; + } // TODO: If the parent Suspense handler already suspended, there's no reason + // to push a nested Suspense handler, because it will get replaced by the + // outer fallback, anyway. Consider this as a future optimization. + + push(suspenseHandlerStackCursor, handler, handler); + + if (shellBoundary === null) { + if (current === null || isCurrentTreeHidden()) { + // This boundary is not visible in the current UI. + shellBoundary = handler; + } else { + var prevState = current.memoizedState; + + if (prevState !== null) { + // This boundary is showing a fallback in the current UI. + shellBoundary = handler; + } + } + } + } + function pushFallbackTreeSuspenseHandler(fiber) { + // We're about to render the fallback. If something in the fallback suspends, + // it's akin to throwing inside of a `catch` block. This boundary should not + // capture. Reuse the existing handler on the stack. + reuseSuspenseHandlerOnStack(fiber); + } + function pushOffscreenSuspenseHandler(fiber) { + if (fiber.tag === OffscreenComponent) { + // A SuspenseList context is only pushed here to avoid a push/pop mismatch. + // Reuse the current value on the stack. + // TODO: We can avoid needing to push here by by forking popSuspenseHandler + // into separate functions for Suspense and Offscreen. + pushSuspenseListContext(fiber, suspenseStackCursor.current); + push(suspenseHandlerStackCursor, fiber, fiber); + + if (shellBoundary !== null); + else { + var current = fiber.alternate; + + if (current !== null) { + var prevState = current.memoizedState; + + if (prevState !== null) { + // This is the first boundary in the stack that's already showing + // a fallback. So everything outside is considered the shell. + shellBoundary = fiber; + } + } + } + } else { + // This is a LegacyHidden component. + reuseSuspenseHandlerOnStack(fiber); + } + } + function reuseSuspenseHandlerOnStack(fiber) { + pushSuspenseListContext(fiber, suspenseStackCursor.current); + push(suspenseHandlerStackCursor, getSuspenseHandler(), fiber); + } + function getSuspenseHandler() { + return suspenseHandlerStackCursor.current; + } + function popSuspenseHandler(fiber) { + pop(suspenseHandlerStackCursor, fiber); + + if (shellBoundary === fiber) { + // Popping back into the shell. + shellBoundary = null; + } + + popSuspenseListContext(fiber); + } // SuspenseList context + // TODO: Move to a separate module? We may change the SuspenseList + // implementation to hide/show in the commit phase, anyway. + + var DefaultSuspenseContext = 0; + var SubtreeSuspenseContextMask = 1; // ForceSuspenseFallback can be used by SuspenseList to force newly added + // items into their fallback state during one of the render passes. + + var ForceSuspenseFallback = 2; + var suspenseStackCursor = createCursor(DefaultSuspenseContext); + function hasSuspenseListContext(parentContext, flag) { + return (parentContext & flag) !== 0; + } + function setDefaultShallowSuspenseListContext(parentContext) { + return parentContext & SubtreeSuspenseContextMask; + } + function setShallowSuspenseListContext(parentContext, shallowContext) { + return (parentContext & SubtreeSuspenseContextMask) | shallowContext; + } + function pushSuspenseListContext(fiber, newContext) { + push(suspenseStackCursor, newContext, fiber); + } + function popSuspenseListContext(fiber) { + pop(suspenseStackCursor, fiber); + } + + // A non-null SuspenseState means that it is blocked for one reason or another. + // - A non-null dehydrated field means it's blocked pending hydration. + // - A non-null dehydrated field can use isSuspenseInstancePending or + // isSuspenseInstanceFallback to query the reason for being dehydrated. + // - A null dehydrated field means it's blocked by something suspending and + // we're currently showing a fallback instead. + + function findFirstSuspended(row) { + var node = row; + + while (node !== null) { + if (node.tag === SuspenseComponent) { + var state = node.memoizedState; + + if (state !== null) { + var dehydrated = state.dehydrated; + + if ( + dehydrated === null || + isSuspenseInstancePending() || + isSuspenseInstanceFallback() + ) { + return node; + } + } + } else if ( + node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't + // keep track of whether it suspended or not. + node.memoizedProps.revealOrder !== undefined + ) { + var didSuspend = (node.flags & DidCapture) !== NoFlags$1; + + if (didSuspend) { + return node; + } + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } + + if (node === row) { + return null; + } + + while (node.sibling === null) { + if (node.return === null || node.return === row) { + return null; + } + + node = node.return; + } + + node.sibling.return = node.return; + node = node.sibling; + } + + return null; + } + + var NoFlags = + /* */ + 0; // Represents whether effect should fire. + + var HasEffect = + /* */ + 1; // Represents the phase in which the effect (not the clean-up) fires. + + var Insertion = + /* */ + 2; + var Layout = + /* */ + 4; + var Passive = + /* */ + 8; + + var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // A linked list of all the roots with pending work. In an idiomatic app, + // there's only a single root, but we do support multi root apps, hence this + // extra complexity. But this module is optimized for the single root case. + + var firstScheduledRoot = null; + var lastScheduledRoot = null; // Used to prevent redundant mircotasks from being scheduled. + + var didScheduleMicrotask = false; // `act` "microtasks" are scheduled on the `act` queue instead of an actual + // microtask, so we have to dedupe those separately. This wouldn't be an issue + // if we required all `act` calls to be awaited, which we might in the future. + + var didScheduleMicrotask_act = false; // Used to quickly bail out of flushSync if there's no sync work to do. + + var mightHavePendingSyncWork = false; + var isFlushingWork = false; + var currentEventTransitionLane = NoLane; + function ensureRootIsScheduled(root) { + // This function is called whenever a root receives an update. It does two + // things 1) it ensures the root is in the root schedule, and 2) it ensures + // there's a pending microtask to process the root schedule. + // + // Most of the actual scheduling logic does not happen until + // `scheduleTaskForRootDuringMicrotask` runs. + // Add the root to the schedule + if (root === lastScheduledRoot || root.next !== null); + else { + if (lastScheduledRoot === null) { + firstScheduledRoot = lastScheduledRoot = root; + } else { + lastScheduledRoot.next = root; + lastScheduledRoot = root; + } + } // Any time a root received an update, we set this to true until the next time + // we process the schedule. If it's false, then we can quickly exit flushSync + // without consulting the schedule. + + mightHavePendingSyncWork = true; // At the end of the current event, go through each of the roots and ensure + // there's a task scheduled for each one at the correct priority. + + if (ReactCurrentActQueue$2.current !== null) { + // We're inside an `act` scope. + if (!didScheduleMicrotask_act) { + didScheduleMicrotask_act = true; + scheduleImmediateTask(processRootScheduleInMicrotask); + } + } else { + if (!didScheduleMicrotask) { + didScheduleMicrotask = true; + scheduleImmediateTask(processRootScheduleInMicrotask); + } + } + + if (!enableDeferRootSchedulingToMicrotask) { + // While this flag is disabled, we schedule the render task immediately + // instead of waiting a microtask. + // TODO: We need to land enableDeferRootSchedulingToMicrotask ASAP to + // unblock additional features we have planned. + scheduleTaskForRootDuringMicrotask(root, now$1()); + } + + if (ReactCurrentActQueue$2.isBatchingLegacy && root.tag === LegacyRoot) { + // Special `act` case: Record whenever a legacy update is scheduled. + ReactCurrentActQueue$2.didScheduleLegacyUpdate = true; + } + } + function flushSyncWorkOnAllRoots() { + // This is allowed to be called synchronously, but the caller should check + // the execution context first. + flushSyncWorkAcrossRoots_impl(false); + } + function flushSyncWorkOnLegacyRootsOnly() { + // This is allowed to be called synchronously, but the caller should check + // the execution context first. + flushSyncWorkAcrossRoots_impl(true); + } + + function flushSyncWorkAcrossRoots_impl(onlyLegacy) { + if (isFlushingWork) { + // Prevent reentrancy. + // TODO: Is this overly defensive? The callers must check the execution + // context first regardless. + return; + } + + if (!mightHavePendingSyncWork) { + // Fast path. There's no sync work to do. + return; + } // There may or may not be synchronous work scheduled. Let's check. + + var didPerformSomeWork; + var errors = null; + isFlushingWork = true; + + do { + didPerformSomeWork = false; + var root = firstScheduledRoot; + + while (root !== null) { + if (onlyLegacy && root.tag !== LegacyRoot); + else { + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = + getWorkInProgressRootRenderLanes(); + var nextLanes = getNextLanes( + root, + root === workInProgressRoot + ? workInProgressRootRenderLanes + : NoLanes + ); + + if (includesSyncLane(nextLanes)) { + // This root has pending sync work. Flush it now. + try { + didPerformSomeWork = true; + performSyncWorkOnRoot(root, nextLanes); + } catch (error) { + // Collect errors so we can rethrow them at the end + if (errors === null) { + errors = [error]; + } else { + errors.push(error); + } + } + } + } + + root = root.next; + } + } while (didPerformSomeWork); + + isFlushingWork = false; // If any errors were thrown, rethrow them right before exiting. + // TODO: Consider returning these to the caller, to allow them to decide + // how/when to rethrow. + + if (errors !== null) { + if (errors.length > 1) { + if (typeof AggregateError === "function") { + // eslint-disable-next-line no-undef + throw new AggregateError(errors); + } else { + for (var i = 1; i < errors.length; i++) { + scheduleImmediateTask(throwError.bind(null, errors[i])); + } + + var firstError = errors[0]; + throw firstError; + } + } else { + var error = errors[0]; + throw error; + } + } + } + + function throwError(error) { + throw error; + } + + function processRootScheduleInMicrotask() { + // This function is always called inside a microtask. It should never be + // called synchronously. + didScheduleMicrotask = false; + + { + didScheduleMicrotask_act = false; + } // We'll recompute this as we iterate through all the roots and schedule them. + + mightHavePendingSyncWork = false; + var currentTime = now$1(); + var prev = null; + var root = firstScheduledRoot; + + while (root !== null) { + var next = root.next; + + if ( + currentEventTransitionLane !== NoLane && + shouldAttemptEagerTransition() + ) { + // A transition was scheduled during an event, but we're going to try to + // render it synchronously anyway. We do this during a popstate event to + // preserve the scroll position of the previous page. + upgradePendingLaneToSync(root, currentEventTransitionLane); + } + + var nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime); + + if (nextLanes === NoLane) { + // This root has no more pending work. Remove it from the schedule. To + // guard against subtle reentrancy bugs, this microtask is the only place + // we do this — you can add roots to the schedule whenever, but you can + // only remove them here. + // Null this out so we know it's been removed from the schedule. + root.next = null; + + if (prev === null) { + // This is the new head of the list + firstScheduledRoot = next; + } else { + prev.next = next; + } + + if (next === null) { + // This is the new tail of the list + lastScheduledRoot = prev; + } + } else { + // This root still has work. Keep it in the list. + prev = root; + + if (includesSyncLane(nextLanes)) { + mightHavePendingSyncWork = true; + } + } + + root = next; + } + + currentEventTransitionLane = NoLane; // At the end of the microtask, flush any pending synchronous work. This has + // to come at the end, because it does actual rendering work that might throw. + + flushSyncWorkOnAllRoots(); + } + + function scheduleTaskForRootDuringMicrotask(root, currentTime) { + // This function is always called inside a microtask, or at the very end of a + // rendering task right before we yield to the main thread. It should never be + // called synchronously. + // + // TODO: Unless enableDeferRootSchedulingToMicrotask is off. We need to land + // that ASAP to unblock additional features we have planned. + // + // This function also never performs React work synchronously; it should + // only schedule work to be performed later, in a separate task or microtask. + // Check if any lanes are being starved by other work. If so, mark them as + // expired so we know to work on those next. + markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. + + var workInProgressRoot = getWorkInProgressRoot(); + var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); + var existingCallbackNode = root.callbackNode; + + if ( + // Check if there's nothing to work on + nextLanes === NoLanes || // If this root is currently suspended and waiting for data to resolve, don't + // schedule a task to render it. We'll either wait for a ping, or wait to + // receive an update. + // + // Suspended render phase + (root === workInProgressRoot && isWorkLoopSuspendedOnData()) || // Suspended commit phase + root.cancelPendingCommit !== null + ) { + // Fast path: There's nothing to work on. + if (existingCallbackNode !== null) { + cancelCallback(existingCallbackNode); + } + + root.callbackNode = null; + root.callbackPriority = NoLane; + return NoLane; + } // Schedule a new callback in the host environment. + + if (includesSyncLane(nextLanes)) { + // Synchronous work is always flushed at the end of the microtask, so we + // don't need to schedule an additional task. + if (existingCallbackNode !== null) { + cancelCallback(existingCallbackNode); + } + + root.callbackPriority = SyncLane; + root.callbackNode = null; + return SyncLane; + } else { + // We use the highest priority lane to represent the priority of the callback. + var existingCallbackPriority = root.callbackPriority; + var newCallbackPriority = getHighestPriorityLane(nextLanes); + + if ( + newCallbackPriority === existingCallbackPriority && // Special case related to `act`. If the currently scheduled task is a + // Scheduler task, rather than an `act` task, cancel it and re-schedule + // on the `act` queue. + !( + ReactCurrentActQueue$2.current !== null && + existingCallbackNode !== fakeActCallbackNode$1 + ) + ) { + // The priority hasn't changed. We can reuse the existing task. + return newCallbackPriority; + } else { + // Cancel the existing callback. We'll schedule a new one below. + cancelCallback(existingCallbackNode); + } + + var schedulerPriorityLevel; + + switch (lanesToEventPriority(nextLanes)) { + case DiscreteEventPriority: + schedulerPriorityLevel = ImmediatePriority; + break; + + case ContinuousEventPriority: + schedulerPriorityLevel = UserBlockingPriority; + break; + + case DefaultEventPriority: + schedulerPriorityLevel = NormalPriority$1; + break; + + case IdleEventPriority: + schedulerPriorityLevel = IdlePriority; + break; + + default: + schedulerPriorityLevel = NormalPriority$1; + break; + } + + var newCallbackNode = scheduleCallback$2( + schedulerPriorityLevel, + performConcurrentWorkOnRoot.bind(null, root) + ); + root.callbackPriority = newCallbackPriority; + root.callbackNode = newCallbackNode; + return newCallbackPriority; + } + } + + function getContinuationForRoot(root, originalCallbackNode) { + // This is called at the end of `performConcurrentWorkOnRoot` to determine + // if we need to schedule a continuation task. + // + // Usually `scheduleTaskForRootDuringMicrotask` only runs inside a microtask; + // however, since most of the logic for determining if we need a continuation + // versus a new task is the same, we cheat a bit and call it here. This is + // only safe to do because we know we're at the end of the browser task. + // So although it's not an actual microtask, it might as well be. + scheduleTaskForRootDuringMicrotask(root, now$1()); + + if (root.callbackNode === originalCallbackNode) { + // The task node scheduled for this root is the same one that's + // currently executed. Need to return a continuation. + return performConcurrentWorkOnRoot.bind(null, root); + } + + return null; + } + var fakeActCallbackNode$1 = {}; + + function scheduleCallback$2(priorityLevel, callback) { + if (ReactCurrentActQueue$2.current !== null) { + // Special case: We're inside an `act` scope (a testing utility). + // Instead of scheduling work in the host environment, add it to a + // fake internal queue that's managed by the `act` implementation. + ReactCurrentActQueue$2.current.push(callback); + return fakeActCallbackNode$1; + } else { + return scheduleCallback$3(priorityLevel, callback); + } + } + + function cancelCallback(callbackNode) { + if (callbackNode === fakeActCallbackNode$1); + else if (callbackNode !== null) { + cancelCallback$1(callbackNode); + } + } + + function scheduleImmediateTask(cb) { + if (ReactCurrentActQueue$2.current !== null) { + // Special case: Inside an `act` scope, we push microtasks to the fake `act` + // callback queue. This is because we currently support calling `act` + // without awaiting the result. The plan is to deprecate that, and require + // that you always await the result so that the microtasks have a chance to + // run. But it hasn't happened yet. + ReactCurrentActQueue$2.current.push(function () { + cb(); + return null; + }); + } // TODO: Can we land supportsMicrotasks? Which environments don't support it? + // Alternatively, can we move this check to the host config? + + { + // If microtasks are not supported, use Scheduler. + scheduleCallback$3(ImmediatePriority, cb); + } + } + + function requestTransitionLane() { + // The algorithm for assigning an update to a lane should be stable for all + // updates at the same priority within the same event. To do this, the + // inputs to the algorithm must be the same. + // + // The trick we use is to cache the first of each of these inputs within an + // event. Then reset the cached values once we can be sure the event is + // over. Our heuristic for that is whenever we enter a concurrent work loop. + if (currentEventTransitionLane === NoLane) { + // All transitions within the same event are assigned the same lane. + currentEventTransitionLane = claimNextTransitionLane(); + } + + return currentEventTransitionLane; + } + + // transition updates that occur while the async action is still in progress + // are treated as part of the action. + // + // The ideal behavior would be to treat each async function as an independent + // action. However, without a mechanism like AsyncContext, we can't tell which + // action an update corresponds to. So instead, we entangle them all into one. + // The listeners to notify once the entangled scope completes. + + var currentEntangledListeners = null; // The number of pending async actions in the entangled scope. + + var currentEntangledPendingCount = 0; // The transition lane shared by all updates in the entangled scope. + + var currentEntangledLane = NoLane; + function requestAsyncActionContext( + actionReturnValue, // If this is provided, this resulting thenable resolves to this value instead + // of the return value of the action. This is a perf trick to avoid composing + // an extra async function. + overrideReturnValue + ) { + // This is an async action. + // + // Return a thenable that resolves once the action scope (i.e. the async + // function passed to startTransition) has finished running. + var thenable = actionReturnValue; + var entangledListeners; + + if (currentEntangledListeners === null) { + // There's no outer async action scope. Create a new one. + entangledListeners = currentEntangledListeners = []; + currentEntangledPendingCount = 0; + currentEntangledLane = requestTransitionLane(); + } else { + entangledListeners = currentEntangledListeners; + } + + currentEntangledPendingCount++; // Create a thenable that represents the result of this action, but doesn't + // resolve until the entire entangled scope has finished. + // + // Expressed using promises: + // const [thisResult] = await Promise.all([thisAction, entangledAction]); + // return thisResult; + + var resultThenable = createResultThenable(entangledListeners); + var resultStatus = "pending"; + var resultValue; + var rejectedReason; + thenable.then( + function (value) { + resultStatus = "fulfilled"; + resultValue = + overrideReturnValue !== null ? overrideReturnValue : value; + pingEngtangledActionScope(); + }, + function (error) { + resultStatus = "rejected"; + rejectedReason = error; + pingEngtangledActionScope(); + } + ); // Attach a listener to fill in the result. + + entangledListeners.push(function () { + switch (resultStatus) { + case "fulfilled": { + var fulfilledThenable = resultThenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = resultValue; + break; + } + + case "rejected": { + var rejectedThenable = resultThenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = rejectedReason; + break; + } + + case "pending": + default: { + // The listener above should have been called first, so `resultStatus` + // should already be set to the correct value. + throw new Error( + "Thenable should have already resolved. This " + + "is a bug in React." + ); + } + } + }); + return resultThenable; + } + function requestSyncActionContext( + actionReturnValue, // If this is provided, this resulting thenable resolves to this value instead + // of the return value of the action. This is a perf trick to avoid composing + // an extra async function. + overrideReturnValue + ) { + var resultValue = + overrideReturnValue !== null ? overrideReturnValue : actionReturnValue; // This is not an async action, but it may be part of an outer async action. + + if (currentEntangledListeners === null) { + return resultValue; + } else { + // Return a thenable that does not resolve until the entangled actions + // have finished. + var entangledListeners = currentEntangledListeners; + var resultThenable = createResultThenable(entangledListeners); + entangledListeners.push(function () { + var fulfilledThenable = resultThenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = resultValue; + }); + return resultThenable; + } + } + + function pingEngtangledActionScope() { + if ( + currentEntangledListeners !== null && + --currentEntangledPendingCount === 0 + ) { + // All the actions have finished. Close the entangled async action scope + // and notify all the listeners. + var listeners = currentEntangledListeners; + currentEntangledListeners = null; + currentEntangledLane = NoLane; + + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; + listener(); + } + } + } + + function createResultThenable(entangledListeners) { + // Waits for the entangled async action to complete, then resolves to the + // result of an individual action. + var resultThenable = { + status: "pending", + value: null, + reason: null, + then: function (resolve) { + // This is a bit of a cheat. `resolve` expects a value of type `S` to be + // passed, but because we're instrumenting the `status` field ourselves, + // and we know this thenable will only be used by React, we also know + // the value isn't actually needed. So we add the resolve function + // directly to the entangled listeners. + // + // This is also why we don't need to check if the thenable is still + // pending; the Suspense implementation already performs that check. + var ping = resolve; + entangledListeners.push(ping); + } + }; + return resultThenable; + } + + function peekEntangledActionLane() { + return currentEntangledLane; + } + + var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, + ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig; + var didWarnAboutMismatchedHooksForComponent; + var didWarnUncachedGetSnapshot; + var didWarnAboutUseWrappedInTryCatch; + var didWarnAboutAsyncClientComponent; + + { + didWarnAboutMismatchedHooksForComponent = new Set(); + didWarnAboutUseWrappedInTryCatch = new Set(); + didWarnAboutAsyncClientComponent = new Set(); + } // The effect "instance" is a shared object that remains the same for the entire + // lifetime of an effect. In Rust terms, a RefCell. We use it to store the + // "destroy" function that is returned from an effect, because that is stateful. + // The field is `undefined` if the effect is unmounted, or if the effect ran + // but is not stateful. We don't explicitly track whether the effect is mounted + // or unmounted because that can be inferred by the hiddenness of the fiber in + // the tree, i.e. whether there is a hidden Offscreen fiber above it. + // + // It's unfortunate that this is stored on a separate object, because it adds + // more memory per effect instance, but it's conceptually sound. I think there's + // likely a better data structure we could use for effects; perhaps just one + // array of effect instances per fiber. But I think this is OK for now despite + // the additional memory and we can follow up with performance + // optimizations later. + // These are set right before calling the component. + + var renderLanes = NoLanes; // The work-in-progress fiber. I've named it differently to distinguish it from + // the work-in-progress hook. + + var currentlyRenderingFiber$1 = null; // Hooks are stored as a linked list on the fiber's memoizedState field. The + // current hook list is the list that belongs to the current fiber. The + // work-in-progress hook list is a new list that will be added to the + // work-in-progress fiber. + + var currentHook = null; + var workInProgressHook = null; // Whether an update was scheduled at any point during the render phase. This + // does not get reset if we do another render pass; only when we're completely + // finished evaluating this component. This is an optimization so we know + // whether we need to clear render phase updates after a throw. + + var didScheduleRenderPhaseUpdate = false; // Where an update was scheduled only during the current render pass. This + // gets reset after each attempt. + // TODO: Maybe there's some way to consolidate this with + // `didScheduleRenderPhaseUpdate`. Or with `numberOfReRenders`. + + var didScheduleRenderPhaseUpdateDuringThisPass = false; + var shouldDoubleInvokeUserFnsInHooksDEV = false; // Counts the number of useId hooks in this component. + + var thenableIndexCounter = 0; + var thenableState = null; // Used for ids that are generated completely client-side (i.e. not during + // hydration). This counter is global, so client ids are not stable across + // render attempts. + + var globalClientIdCounter = 0; + var RE_RENDER_LIMIT = 25; // In DEV, this is the name of the currently executing primitive hook + + var currentHookNameInDev = null; // In DEV, this list ensures that hooks are called in the same order between renders. + // The list stores the order of hooks used during the initial render (mount). + // Subsequent renders (updates) reference this list. + + var hookTypesDev = null; + var hookTypesUpdateIndexDev = -1; // In DEV, this tracks whether currently rendering component needs to ignore + // the dependencies for Hooks that need them (e.g. useEffect or useMemo). + // When true, such Hooks will always be "remounted". Only used during hot reload. + + var ignorePreviousDependencies = false; + + function mountHookTypesDev() { + { + var hookName = currentHookNameInDev; + + if (hookTypesDev === null) { + hookTypesDev = [hookName]; + } else { + hookTypesDev.push(hookName); + } + } + } + + function updateHookTypesDev() { + { + var hookName = currentHookNameInDev; + + if (hookTypesDev !== null) { + hookTypesUpdateIndexDev++; + + if (hookTypesDev[hookTypesUpdateIndexDev] !== hookName) { + warnOnHookMismatchInDev(hookName); + } + } + } + } + + function checkDepsAreArrayDev(deps) { + { + if (deps !== undefined && deps !== null && !isArray(deps)) { + // Verify deps, but only on mount to avoid extra checks. + // It's unlikely their type would change as usually you define them inline. + 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 + ); + } + } + } + + function warnOnHookMismatchInDev(currentHookName) { + { + var componentName = getComponentNameFromFiber( + currentlyRenderingFiber$1 + ); + + if (!didWarnAboutMismatchedHooksForComponent.has(componentName)) { + didWarnAboutMismatchedHooksForComponent.add(componentName); + + if (hookTypesDev !== null) { + var table = ""; + var secondColumnStart = 30; + + for (var i = 0; i <= hookTypesUpdateIndexDev; i++) { + var oldHookName = hookTypesDev[i]; + var newHookName = + i === hookTypesUpdateIndexDev ? currentHookName : oldHookName; + var row = i + 1 + ". " + oldHookName; // Extra space so second column lines up + // lol @ IE not supporting String#repeat + + while (row.length < secondColumnStart) { + row += " "; + } + + row += newHookName + "\n"; + table += row; + } + + 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 + ); + } + } + } + } + + function warnIfAsyncClientComponent(Component, componentDoesIncludeHooks) { + { + // This dev-only check only works for detecting native async functions, + // not transpiled ones. There's also a prod check that we use to prevent + // async client components from crashing the app; the prod one works even + // for transpiled async functions. Neither mechanism is completely + // bulletproof but together they cover the most common cases. + var isAsyncFunction = // $FlowIgnore[method-unbinding] + Object.prototype.toString.call(Component) === + "[object AsyncFunction]"; + + if (isAsyncFunction) { + // Encountered an async Client Component. This is not yet supported, + // except in certain constrained cases, like during a route navigation. + var componentName = getComponentNameFromFiber( + currentlyRenderingFiber$1 + ); + + if (!didWarnAboutAsyncClientComponent.has(componentName)) { + didWarnAboutAsyncClientComponent.add(componentName); // Check if this is a sync update. We use the "root" render lanes here + // because the "subtree" render lanes may include additional entangled + // lanes related to revealing previously hidden content. + + var root = getWorkInProgressRoot(); + var rootRenderLanes = getWorkInProgressRootRenderLanes(); + + if (root !== null && includesBlockingLane(root, rootRenderLanes)) { + error( + "async/await is not yet supported in Client Components, only " + + "Server Components. This error is often caused by accidentally " + + "adding `'use client'` to a module that was originally written " + + "for the server." + ); + } else { + // This is a concurrent (Transition, Retry, etc) render. We don't + // warn in these cases. + // + // However, Async Components are forbidden to include hooks, even + // during a transition, so let's check for that here. + // + // TODO: Add a corresponding warning to Server Components runtime. + if (componentDoesIncludeHooks) { + error( + "Hooks are not supported inside an async component. This " + + "error is often caused by accidentally adding `'use client'` " + + "to a module that was originally written for the server." + ); + } + } + } + } + } + } + + function throwInvalidHookError() { + 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." + ); + } + + function areHookInputsEqual(nextDeps, prevDeps) { + { + if (ignorePreviousDependencies) { + // Only true when this component is being hot reloaded. + return false; + } + } + + if (prevDeps === null) { + { + 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 + ); + } + + return false; + } + + { + // Don't bother comparing lengths in prod because these arrays should be + // passed inline. + if (nextDeps.length !== prevDeps.length) { + 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(", ") + "]" + ); + } + } // $FlowFixMe[incompatible-use] found when upgrading Flow + + for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + if (objectIs(nextDeps[i], prevDeps[i])) { + continue; + } + + return false; + } + + return true; + } + + function renderWithHooks( + current, + workInProgress, + Component, + props, + secondArg, + nextRenderLanes + ) { + renderLanes = nextRenderLanes; + currentlyRenderingFiber$1 = workInProgress; + + { + hookTypesDev = current !== null ? current._debugHookTypes : null; + hookTypesUpdateIndexDev = -1; // Used for hot reloading: + + ignorePreviousDependencies = + current !== null && current.type !== workInProgress.type; + } + + workInProgress.memoizedState = null; + workInProgress.updateQueue = null; + workInProgress.lanes = NoLanes; // The following should have already been reset + // currentHook = null; + // workInProgressHook = null; + // didScheduleRenderPhaseUpdate = false; + // localIdCounter = 0; + // thenableIndexCounter = 0; + // thenableState = null; + // TODO Warn if no hooks are used at all during mount, then some are used during update. + // Currently we will identify the update render as a mount because memoizedState === null. + // This is tricky because it's valid for certain types of components (e.g. React.lazy) + // Using memoizedState to differentiate between mount/update only works if at least one stateful hook is used. + // Non-stateful hooks (e.g. context) don't get added to memoizedState, + // so memoizedState would be null during updates and mounts. + + { + if (current !== null && current.memoizedState !== null) { + ReactCurrentDispatcher$1.current = HooksDispatcherOnUpdateInDEV; + } else if (hookTypesDev !== null) { + // This dispatcher handles an edge case where a component is updating, + // but no stateful hooks have been used. + // We want to match the production code behavior (which will use HooksDispatcherOnMount), + // but with the extra DEV validation to ensure hooks ordering hasn't changed. + // This dispatcher does that. + ReactCurrentDispatcher$1.current = + HooksDispatcherOnMountWithHookTypesInDEV; + } else { + ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; + } + } // In Strict Mode, during development, user functions are double invoked to + // help detect side effects. The logic for how this is implemented for in + // hook components is a bit complex so let's break it down. + // + // We will invoke the entire component function twice. However, during the + // second invocation of the component, the hook state from the first + // invocation will be reused. That means things like `useMemo` functions won't + // run again, because the deps will match and the memoized result will + // be reused. + // + // We want memoized functions to run twice, too, so account for this, user + // functions are double invoked during the *first* invocation of the component + // function, and are *not* double invoked during the second incovation: + // + // - First execution of component function: user functions are double invoked + // - Second execution of component function (in Strict Mode, during + // development): user functions are not double invoked. + // + // This is intentional for a few reasons; most importantly, it's because of + // how `use` works when something suspends: it reuses the promise that was + // passed during the first attempt. This is itself a form of memoization. + // We need to be able to memoize the reactive inputs to the `use` call using + // a hook (i.e. `useMemo`), which means, the reactive inputs to `use` must + // come from the same component invocation as the output. + // + // There are plenty of tests to ensure this behavior is correct. + + var shouldDoubleRenderDEV = + (workInProgress.mode & StrictLegacyMode) !== NoMode; + shouldDoubleInvokeUserFnsInHooksDEV = shouldDoubleRenderDEV; + var children = Component(props, secondArg); + shouldDoubleInvokeUserFnsInHooksDEV = false; // Check if there was a render phase update + + if (didScheduleRenderPhaseUpdateDuringThisPass) { + // Keep rendering until the component stabilizes (there are no more render + // phase updates). + children = renderWithHooksAgain( + workInProgress, + Component, + props, + secondArg + ); + } + + if (shouldDoubleRenderDEV) { + // In development, components are invoked twice to help detect side effects. + setIsStrictModeForDevtools(true); + + try { + children = renderWithHooksAgain( + workInProgress, + Component, + props, + secondArg + ); + } finally { + setIsStrictModeForDevtools(false); + } + } + + finishRenderingHooks(current, workInProgress, Component); + return children; + } + + function finishRenderingHooks(current, workInProgress, Component) { + { + workInProgress._debugHookTypes = hookTypesDev; + var componentDoesIncludeHooks = + workInProgressHook !== null || thenableIndexCounter !== 0; + warnIfAsyncClientComponent(Component, componentDoesIncludeHooks); + } // We can assume the previous dispatcher is always this one, since we set it + // at the beginning of the render phase and there's no re-entrance. + + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; // This check uses currentHook so that it works the same in DEV and prod bundles. + // hookTypesDev could catch more cases (e.g. context) but only in DEV bundles. + + var didRenderTooFewHooks = + currentHook !== null && currentHook.next !== null; + renderLanes = NoLanes; + currentlyRenderingFiber$1 = null; + currentHook = null; + workInProgressHook = null; + + { + currentHookNameInDev = null; + hookTypesDev = null; + hookTypesUpdateIndexDev = -1; // Confirm that a static flag was not added or removed since the last + // render. If this fires, it suggests that we incorrectly reset the static + // flags in some other part of the codebase. This has happened before, for + // example, in the SuspenseList implementation. + + if ( + current !== null && + (current.flags & StaticMask) !== + (workInProgress.flags & StaticMask) && // Disable this warning in legacy mode, because legacy Suspense is weird + // and creates false positives. To make this work in legacy mode, we'd + // need to mark fibers that commit in an incomplete state, somehow. For + // now I'll disable the warning that most of the bugs that would trigger + // it are either exclusive to concurrent mode or exist in both. + (current.mode & ConcurrentMode) !== NoMode + ) { + error( + "Internal React error: Expected static flag was missing. Please " + + "notify the React team." + ); + } + } + + didScheduleRenderPhaseUpdate = false; // This is reset by checkDidRenderIdHook + // localIdCounter = 0; + + thenableIndexCounter = 0; + thenableState = null; + + if (didRenderTooFewHooks) { + throw new Error( + "Rendered fewer hooks than expected. This may be caused by an accidental " + + "early return statement." + ); + } + + if (enableLazyContextPropagation) { + if (current !== null) { + if (!checkIfWorkInProgressReceivedUpdate()) { + // If there were no changes to props or state, we need to check if there + // was a context change. We didn't already do this because there's no + // 1:1 correspondence between dependencies and hooks. Although, because + // there almost always is in the common case (`readContext` is an + // internal API), we could compare in there. OTOH, we only hit this case + // if everything else bails out, so on the whole it might be better to + // keep the comparison out of the common path. + var currentDependencies = current.dependencies; + + if ( + currentDependencies !== null && + checkIfContextChanged(currentDependencies) + ) { + markWorkInProgressReceivedUpdate(); + } + } + } + } + + { + if (checkIfUseWrappedInTryCatch()) { + var componentName = + getComponentNameFromFiber(workInProgress) || "Unknown"; + + if ( + !didWarnAboutUseWrappedInTryCatch.has(componentName) && // This warning also fires if you suspend with `use` inside an + // async component. Since we warn for that above, we'll silence this + // second warning by checking here. + !didWarnAboutAsyncClientComponent.has(componentName) + ) { + didWarnAboutUseWrappedInTryCatch.add(componentName); + + error( + "`use` was called from inside a try/catch block. This is not allowed " + + "and can lead to unexpected behavior. To handle errors triggered " + + "by `use`, wrap your component in a error boundary." + ); + } + } + } + } + + function replaySuspendedComponentWithHooks( + current, + workInProgress, + Component, + props, + secondArg + ) { + // This function is used to replay a component that previously suspended, + // after its data resolves. + // + // It's a simplified version of renderWithHooks, but it doesn't need to do + // most of the set up work because they weren't reset when we suspended; they + // only get reset when the component either completes (finishRenderingHooks) + // or unwinds (resetHooksOnUnwind). + { + hookTypesUpdateIndexDev = -1; // Used for hot reloading: + + ignorePreviousDependencies = + current !== null && current.type !== workInProgress.type; + } + + var children = renderWithHooksAgain( + workInProgress, + Component, + props, + secondArg + ); + finishRenderingHooks(current, workInProgress, Component); + return children; + } + + function renderWithHooksAgain(workInProgress, Component, props, secondArg) { + // This is used to perform another render pass. It's used when setState is + // called during render, and for double invoking components in Strict Mode + // during development. + // + // The state from the previous pass is reused whenever possible. So, state + // updates that were already processed are not processed again, and memoized + // functions (`useMemo`) are not invoked again. + // + // Keep rendering in a loop for as long as render phase updates continue to + // be scheduled. Use a counter to prevent infinite loops. + currentlyRenderingFiber$1 = workInProgress; + var numberOfReRenders = 0; + var children; + + do { + if (didScheduleRenderPhaseUpdateDuringThisPass) { + // It's possible that a use() value depended on a state that was updated in + // this rerender, so we need to watch for different thenables this time. + thenableState = null; + } + + thenableIndexCounter = 0; + didScheduleRenderPhaseUpdateDuringThisPass = false; + + if (numberOfReRenders >= RE_RENDER_LIMIT) { + throw new Error( + "Too many re-renders. React limits the number of renders to prevent " + + "an infinite loop." + ); + } + + numberOfReRenders += 1; + + { + // Even when hot reloading, allow dependencies to stabilize + // after first render to prevent infinite render phase updates. + ignorePreviousDependencies = false; + } // Start over from the beginning of the list + + currentHook = null; + workInProgressHook = null; + workInProgress.updateQueue = null; + + { + // Also validate hook order for cascading updates. + hookTypesUpdateIndexDev = -1; + } + + ReactCurrentDispatcher$1.current = HooksDispatcherOnRerenderInDEV; + children = Component(props, secondArg); + } while (didScheduleRenderPhaseUpdateDuringThisPass); + + return children; + } + function bailoutHooks(current, workInProgress, lanes) { + workInProgress.updateQueue = current.updateQueue; // TODO: Don't need to reset the flags here, because they're reset in the + // complete phase (bubbleProperties). + + if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { + workInProgress.flags &= ~( + MountPassiveDev | + MountLayoutDev | + Passive$1 | + Update + ); + } else { + workInProgress.flags &= ~(Passive$1 | Update); + } + + current.lanes = removeLanes(current.lanes, lanes); + } + function resetHooksAfterThrow() { + // This is called immediaetly after a throw. It shouldn't reset the entire + // module state, because the work loop might decide to replay the component + // again without rewinding. + // + // It should only reset things like the current dispatcher, to prevent hooks + // from being called outside of a component. + currentlyRenderingFiber$1 = null; // We can assume the previous dispatcher is always this one, since we set it + // at the beginning of the render phase and there's no re-entrance. + + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; + } + function resetHooksOnUnwind(workInProgress) { + if (didScheduleRenderPhaseUpdate) { + // There were render phase updates. These are only valid for this render + // phase, which we are now aborting. Remove the updates from the queues so + // they do not persist to the next render. Do not remove updates from hooks + // that weren't processed. + // + // Only reset the updates from the queue if it has a clone. If it does + // not have a clone, that means it wasn't processed, and the updates were + // scheduled before we entered the render phase. + var hook = workInProgress.memoizedState; + + while (hook !== null) { + var queue = hook.queue; + + if (queue !== null) { + queue.pending = null; + } + + hook = hook.next; + } + + didScheduleRenderPhaseUpdate = false; + } + + renderLanes = NoLanes; + currentlyRenderingFiber$1 = null; + currentHook = null; + workInProgressHook = null; + + { + hookTypesDev = null; + hookTypesUpdateIndexDev = -1; + currentHookNameInDev = null; + } + + didScheduleRenderPhaseUpdateDuringThisPass = false; + thenableIndexCounter = 0; + thenableState = null; + } + + function mountWorkInProgressHook() { + var hook = { + memoizedState: null, + baseState: null, + baseQueue: null, + queue: null, + next: null + }; + + if (workInProgressHook === null) { + // This is the first hook in the list + currentlyRenderingFiber$1.memoizedState = workInProgressHook = hook; + } else { + // Append to the end of the list + workInProgressHook = workInProgressHook.next = hook; + } + + return workInProgressHook; + } + + function updateWorkInProgressHook() { + // This function is used both for updates and for re-renders triggered by a + // render phase update. It assumes there is either a current hook we can + // clone, or a work-in-progress hook from a previous render pass that we can + // use as a base. + var nextCurrentHook; + + if (currentHook === null) { + var current = currentlyRenderingFiber$1.alternate; + + if (current !== null) { + nextCurrentHook = current.memoizedState; + } else { + nextCurrentHook = null; + } + } else { + nextCurrentHook = currentHook.next; + } + + var nextWorkInProgressHook; + + if (workInProgressHook === null) { + nextWorkInProgressHook = currentlyRenderingFiber$1.memoizedState; + } else { + nextWorkInProgressHook = workInProgressHook.next; + } + + if (nextWorkInProgressHook !== null) { + // There's already a work-in-progress. Reuse it. + workInProgressHook = nextWorkInProgressHook; + nextWorkInProgressHook = workInProgressHook.next; + currentHook = nextCurrentHook; + } else { + // Clone from the current hook. + if (nextCurrentHook === null) { + var currentFiber = currentlyRenderingFiber$1.alternate; + + if (currentFiber === null) { + // This is the initial render. This branch is reached when the component + // suspends, resumes, then renders an additional hook. + // Should never be reached because we should switch to the mount dispatcher first. + throw new Error( + "Update hook called on initial render. This is likely a bug in React. Please file an issue." + ); + } else { + // This is an update. We should always have a current hook. + throw new Error( + "Rendered more hooks than during the previous render." + ); + } + } + + currentHook = nextCurrentHook; + var newHook = { + memoizedState: currentHook.memoizedState, + baseState: currentHook.baseState, + baseQueue: currentHook.baseQueue, + queue: currentHook.queue, + next: null + }; + + if (workInProgressHook === null) { + // This is the first hook in the list. + currentlyRenderingFiber$1.memoizedState = workInProgressHook = + newHook; + } else { + // Append to the end of the list. + workInProgressHook = workInProgressHook.next = newHook; + } + } + + return workInProgressHook; + } // NOTE: defining two versions of this function to avoid size impact when this feature is disabled. + // Previously this function was inlined, the additional `memoCache` property makes it not inlined. + + var createFunctionComponentUpdateQueue; + + { + createFunctionComponentUpdateQueue = function () { + return { + lastEffect: null, + events: null, + stores: null, + memoCache: null + }; + }; + } + + function useThenable(thenable) { + // Track the position of the thenable within this fiber. + var index = thenableIndexCounter; + thenableIndexCounter += 1; + + if (thenableState === null) { + thenableState = createThenableState(); + } + + var result = trackUsedThenable(thenableState, thenable, index); + + if ( + currentlyRenderingFiber$1.alternate === null && + (workInProgressHook === null + ? currentlyRenderingFiber$1.memoizedState === null + : workInProgressHook.next === null) + ) { + // Initial render, and either this is the first time the component is + // called, or there were no Hooks called after this use() the previous + // time (perhaps because it threw). Subsequent Hook calls should use the + // mount dispatcher. + { + ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; + } + } + + return result; + } + + function use(usable) { + if (usable !== null && typeof usable === "object") { + // $FlowFixMe[method-unbinding] + if (typeof usable.then === "function") { + // This is a thenable. + var thenable = usable; + return useThenable(thenable); + } else if ( + usable.$$typeof === REACT_CONTEXT_TYPE || + usable.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + var context = usable; + return readContext(context); + } + } // eslint-disable-next-line react-internal/safe-string-coercion + + throw new Error( + "An unsupported type was passed to use(): " + String(usable) + ); + } + + function useMemoCache(size) { + var memoCache = null; // Fast-path, load memo cache from wip fiber if already prepared + + var updateQueue = currentlyRenderingFiber$1.updateQueue; + + if (updateQueue !== null) { + memoCache = updateQueue.memoCache; + } // Otherwise clone from the current fiber + + if (memoCache == null) { + var current = currentlyRenderingFiber$1.alternate; + + if (current !== null) { + var currentUpdateQueue = current.updateQueue; + + if (currentUpdateQueue !== null) { + var currentMemoCache = currentUpdateQueue.memoCache; + + if (currentMemoCache != null) { + memoCache = { + data: currentMemoCache.data.map(function (array) { + return array.slice(); + }), + index: 0 + }; + } + } + } + } // Finally fall back to allocating a fresh instance of the cache + + if (memoCache == null) { + memoCache = { + data: [], + index: 0 + }; + } + + if (updateQueue === null) { + updateQueue = createFunctionComponentUpdateQueue(); + currentlyRenderingFiber$1.updateQueue = updateQueue; + } + + updateQueue.memoCache = memoCache; + var data = memoCache.data[memoCache.index]; + + if (data === undefined) { + data = memoCache.data[memoCache.index] = new Array(size); + + for (var i = 0; i < size; i++) { + data[i] = REACT_MEMO_CACHE_SENTINEL; + } + } else if (data.length !== size) { + // TODO: consider warning or throwing here + { + error( + "Expected a constant size argument for each invocation of useMemoCache. " + + "The previous cache was allocated with size %s but size %s was requested.", + data.length, + size + ); + } + } + + memoCache.index++; + return data; + } + + function basicStateReducer(state, action) { + // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types + return typeof action === "function" ? action(state) : action; + } + + function mountReducer(reducer, initialArg, init) { + var hook = mountWorkInProgressHook(); + var initialState; + + if (init !== undefined) { + initialState = init(initialArg); + } else { + initialState = initialArg; + } + + hook.memoizedState = hook.baseState = initialState; + var queue = { + pending: null, + lanes: NoLanes, + dispatch: null, + lastRenderedReducer: reducer, + lastRenderedState: initialState + }; + hook.queue = queue; + var dispatch = (queue.dispatch = dispatchReducerAction.bind( + null, + currentlyRenderingFiber$1, + queue + )); + return [hook.memoizedState, dispatch]; + } + + function updateReducer(reducer, initialArg, init) { + var hook = updateWorkInProgressHook(); + return updateReducerImpl(hook, currentHook, reducer); + } + + function updateReducerImpl(hook, current, reducer) { + var queue = hook.queue; + + if (queue === null) { + throw new Error( + "Should have a queue. This is likely a bug in React. Please file an issue." + ); + } + + queue.lastRenderedReducer = reducer; // The last rebase update that is NOT part of the base state. + + var baseQueue = hook.baseQueue; // The last pending update that hasn't been processed yet. + + var pendingQueue = queue.pending; + + if (pendingQueue !== null) { + // We have new updates that haven't been processed yet. + // We'll add them to the base queue. + if (baseQueue !== null) { + // Merge the pending queue and the base queue. + var baseFirst = baseQueue.next; + var pendingFirst = pendingQueue.next; + baseQueue.next = pendingFirst; + pendingQueue.next = baseFirst; + } + + { + if (current.baseQueue !== baseQueue) { + // Internal invariant that should never happen, but feasibly could in + // the future if we implement resuming, or some form of that. + error( + "Internal error: Expected work-in-progress queue to be a clone. " + + "This is a bug in React." + ); + } + } + + current.baseQueue = baseQueue = pendingQueue; + queue.pending = null; + } + + if (baseQueue !== null) { + // We have a queue to process. + var first = baseQueue.next; + var newState = hook.baseState; + var newBaseState = null; + var newBaseQueueFirst = null; + var newBaseQueueLast = null; + var update = first; + + do { + // An extra OffscreenLane bit is added to updates that were made to + // a hidden tree, so that we can distinguish them from updates that were + // already there when the tree was hidden. + var updateLane = removeLanes(update.lane, OffscreenLane); + var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then + // it's not a "base" update and we should disregard the extra base lanes + // that were added to renderLanes when we entered the Offscreen tree. + + var shouldSkipUpdate = isHiddenUpdate + ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) + : !isSubsetOfLanes(renderLanes, updateLane); + + if (shouldSkipUpdate) { + // Priority is insufficient. Skip this update. If this is the first + // skipped update, the previous update/state is the new base + // update/state. + var clone = { + lane: updateLane, + revertLane: update.revertLane, + action: update.action, + hasEagerState: update.hasEagerState, + eagerState: update.eagerState, + next: null + }; + + if (newBaseQueueLast === null) { + newBaseQueueFirst = newBaseQueueLast = clone; + newBaseState = newState; + } else { + newBaseQueueLast = newBaseQueueLast.next = clone; + } // Update the remaining priority in the queue. + // TODO: Don't need to accumulate this. Instead, we can remove + // renderLanes from the original lanes. + + currentlyRenderingFiber$1.lanes = mergeLanes( + currentlyRenderingFiber$1.lanes, + updateLane + ); + markSkippedUpdateLanes(updateLane); + } else { + // This update does have sufficient priority. + // Check if this is an optimistic update. + var revertLane = update.revertLane; + + if (!enableAsyncActions || revertLane === NoLane) { + // This is not an optimistic update, and we're going to apply it now. + // But, if there were earlier updates that were skipped, we need to + // leave this update in the queue so it can be rebased later. + if (newBaseQueueLast !== null) { + var _clone = { + // This update is going to be committed so we never want uncommit + // it. Using NoLane works because 0 is a subset of all bitmasks, so + // this will never be skipped by the check above. + lane: NoLane, + revertLane: NoLane, + action: update.action, + hasEagerState: update.hasEagerState, + eagerState: update.eagerState, + next: null + }; + newBaseQueueLast = newBaseQueueLast.next = _clone; + } + } else { + // This is an optimistic update. If the "revert" priority is + // sufficient, don't apply the update. Otherwise, apply the update, + // but leave it in the queue so it can be either reverted or + // rebased in a subsequent render. + if (isSubsetOfLanes(renderLanes, revertLane)) { + // The transition that this optimistic update is associated with + // has finished. Pretend the update doesn't exist by skipping + // over it. + update = update.next; + continue; + } else { + var _clone2 = { + // Once we commit an optimistic update, we shouldn't uncommit it + // until the transition it is associated with has finished + // (represented by revertLane). Using NoLane here works because 0 + // is a subset of all bitmasks, so this will never be skipped by + // the check above. + lane: NoLane, + // Reuse the same revertLane so we know when the transition + // has finished. + revertLane: update.revertLane, + action: update.action, + hasEagerState: update.hasEagerState, + eagerState: update.eagerState, + next: null + }; + + if (newBaseQueueLast === null) { + newBaseQueueFirst = newBaseQueueLast = _clone2; + newBaseState = newState; + } else { + newBaseQueueLast = newBaseQueueLast.next = _clone2; + } // Update the remaining priority in the queue. + // TODO: Don't need to accumulate this. Instead, we can remove + // renderLanes from the original lanes. + + currentlyRenderingFiber$1.lanes = mergeLanes( + currentlyRenderingFiber$1.lanes, + revertLane + ); + markSkippedUpdateLanes(revertLane); + } + } // Process this update. + + var action = update.action; + + if (shouldDoubleInvokeUserFnsInHooksDEV) { + reducer(newState, action); + } + + if (update.hasEagerState) { + // If this update is a state update (not a reducer) and was processed eagerly, + // we can use the eagerly computed state + newState = update.eagerState; + } else { + newState = reducer(newState, action); + } + } + + update = update.next; + } while (update !== null && update !== first); + + if (newBaseQueueLast === null) { + newBaseState = newState; + } else { + newBaseQueueLast.next = newBaseQueueFirst; + } // Mark that the fiber performed work, but only if the new state is + // different from the current state. + + if (!objectIs(newState, hook.memoizedState)) { + markWorkInProgressReceivedUpdate(); + } + + hook.memoizedState = newState; + hook.baseState = newBaseState; + hook.baseQueue = newBaseQueueLast; + queue.lastRenderedState = newState; + } + + if (baseQueue === null) { + // `queue.lanes` is used for entangling transitions. We can set it back to + // zero once the queue is empty. + queue.lanes = NoLanes; + } + + var dispatch = queue.dispatch; + return [hook.memoizedState, dispatch]; + } + + function rerenderReducer(reducer, initialArg, init) { + var hook = updateWorkInProgressHook(); + var queue = hook.queue; + + if (queue === null) { + throw new Error( + "Should have a queue. This is likely a bug in React. Please file an issue." + ); + } + + queue.lastRenderedReducer = reducer; // This is a re-render. Apply the new render phase updates to the previous + // work-in-progress hook. + + var dispatch = queue.dispatch; + var lastRenderPhaseUpdate = queue.pending; + var newState = hook.memoizedState; + + if (lastRenderPhaseUpdate !== null) { + // The queue doesn't persist past this render pass. + queue.pending = null; + var firstRenderPhaseUpdate = lastRenderPhaseUpdate.next; + var update = firstRenderPhaseUpdate; + + do { + // Process this render phase update. We don't have to check the + // priority because it will always be the same as the current + // render's. + var action = update.action; + newState = reducer(newState, action); + update = update.next; + } while (update !== firstRenderPhaseUpdate); // Mark that the fiber performed work, but only if the new state is + // different from the current state. + + if (!objectIs(newState, hook.memoizedState)) { + markWorkInProgressReceivedUpdate(); + } + + hook.memoizedState = newState; // Don't persist the state accumulated from the render phase updates to + // the base state unless the queue is empty. + // TODO: Not sure if this is the desired semantics, but it's what we + // do for gDSFP. I can't remember why. + + if (hook.baseQueue === null) { + hook.baseState = newState; + } + + queue.lastRenderedState = newState; + } + + return [newState, dispatch]; + } + + function mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { + var fiber = currentlyRenderingFiber$1; + var hook = mountWorkInProgressHook(); + var nextSnapshot; + + { + nextSnapshot = getSnapshot(); + + { + if (!didWarnUncachedGetSnapshot) { + var cachedSnapshot = getSnapshot(); + + if (!objectIs(nextSnapshot, cachedSnapshot)) { + error( + "The result of getSnapshot should be cached to avoid an infinite loop" + ); + + didWarnUncachedGetSnapshot = true; + } + } + } // Unless we're rendering a blocking lane, schedule a consistency check. + // Right before committing, we will walk the tree and check if any of the + // stores were mutated. + // + // We won't do this if we're hydrating server-rendered content, because if + // the content is stale, it's already visible anyway. Instead we'll patch + // it up in a passive effect. + + var root = getWorkInProgressRoot(); + + if (root === null) { + throw new Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + } + + var rootRenderLanes = getWorkInProgressRootRenderLanes(); + + if (!includesBlockingLane(root, rootRenderLanes)) { + pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); + } + } // Read the current snapshot from the store on every render. This breaks the + // normal rules of React, and only works because store updates are + // always synchronous. + + hook.memoizedState = nextSnapshot; + var inst = { + value: nextSnapshot, + getSnapshot: getSnapshot + }; + hook.queue = inst; // Schedule an effect to subscribe to the store. + + mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [ + subscribe + ]); // Schedule an effect to update the mutable instance fields. We will update + // this whenever subscribe, getSnapshot, or value changes. Because there's no + // clean-up function, and we track the deps correctly, we can call pushEffect + // directly, without storing any additional state. For the same reason, we + // don't need to set a static flag, either. + + fiber.flags |= Passive$1; + pushEffect( + HasEffect | Passive, + updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), + createEffectInstance(), + null + ); + return nextSnapshot; + } + + function updateSyncExternalStore( + subscribe, + getSnapshot, + getServerSnapshot + ) { + var fiber = currentlyRenderingFiber$1; + var hook = updateWorkInProgressHook(); // Read the current snapshot from the store on every render. This breaks the + // normal rules of React, and only works because store updates are + // always synchronous. + + var nextSnapshot; + + { + nextSnapshot = getSnapshot(); + + { + if (!didWarnUncachedGetSnapshot) { + var cachedSnapshot = getSnapshot(); + + if (!objectIs(nextSnapshot, cachedSnapshot)) { + error( + "The result of getSnapshot should be cached to avoid an infinite loop" + ); + + didWarnUncachedGetSnapshot = true; + } + } + } + } + + var prevSnapshot = (currentHook || hook).memoizedState; + var snapshotChanged = !objectIs(prevSnapshot, nextSnapshot); + + if (snapshotChanged) { + hook.memoizedState = nextSnapshot; + markWorkInProgressReceivedUpdate(); + } + + var inst = hook.queue; + updateEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [ + subscribe + ]); // Whenever getSnapshot or subscribe changes, we need to check in the + // commit phase if there was an interleaved mutation. In concurrent mode + // this can happen all the time, but even in synchronous mode, an earlier + // effect may have mutated the store. + + if ( + inst.getSnapshot !== getSnapshot || + snapshotChanged || // Check if the subscribe function changed. We can save some memory by + // checking whether we scheduled a subscription effect above. + (workInProgressHook !== null && + workInProgressHook.memoizedState.tag & HasEffect) + ) { + fiber.flags |= Passive$1; + pushEffect( + HasEffect | Passive, + updateStoreInstance.bind( + null, + fiber, + inst, + nextSnapshot, + getSnapshot + ), + createEffectInstance(), + null + ); // Unless we're rendering a blocking lane, schedule a consistency check. + // Right before committing, we will walk the tree and check if any of the + // stores were mutated. + + var root = getWorkInProgressRoot(); + + if (root === null) { + throw new Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + } + + if (!includesBlockingLane(root, renderLanes)) { + pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); + } + } + + return nextSnapshot; + } + + function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) { + fiber.flags |= StoreConsistency; + var check = { + getSnapshot: getSnapshot, + value: renderedSnapshot + }; + var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; + + if (componentUpdateQueue === null) { + componentUpdateQueue = createFunctionComponentUpdateQueue(); + currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; + componentUpdateQueue.stores = [check]; + } else { + var stores = componentUpdateQueue.stores; + + if (stores === null) { + componentUpdateQueue.stores = [check]; + } else { + stores.push(check); + } + } + } + + function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) { + // These are updated in the passive phase + inst.value = nextSnapshot; + inst.getSnapshot = getSnapshot; // Something may have been mutated in between render and commit. This could + // have been in an event that fired before the passive effects, or it could + // have been in a layout effect. In that case, we would have used the old + // snapsho and getSnapshot values to bail out. We need to check one more time. + + if (checkIfSnapshotChanged(inst)) { + // Force a re-render. + forceStoreRerender(fiber); + } + } + + function subscribeToStore(fiber, inst, subscribe) { + var handleStoreChange = function () { + // The store changed. Check if the snapshot changed since the last time we + // read from the store. + if (checkIfSnapshotChanged(inst)) { + // Force a re-render. + forceStoreRerender(fiber); + } + }; // Subscribe to the store and return a clean-up function. + + return subscribe(handleStoreChange); + } + + function checkIfSnapshotChanged(inst) { + var latestGetSnapshot = inst.getSnapshot; + var prevValue = inst.value; + + try { + var nextValue = latestGetSnapshot(); + return !objectIs(prevValue, nextValue); + } catch (error) { + return true; + } + } + + function forceStoreRerender(fiber) { + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + } + + function mountStateImpl(initialState) { + var hook = mountWorkInProgressHook(); + + if (typeof initialState === "function") { + // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types + initialState = initialState(); + } + + hook.memoizedState = hook.baseState = initialState; + var queue = { + pending: null, + lanes: NoLanes, + dispatch: null, + lastRenderedReducer: basicStateReducer, + lastRenderedState: initialState + }; + hook.queue = queue; + return hook; + } + + function mountState(initialState) { + var hook = mountStateImpl(initialState); + var queue = hook.queue; + var dispatch = dispatchSetState.bind( + null, + currentlyRenderingFiber$1, + queue + ); + queue.dispatch = dispatch; + return [hook.memoizedState, dispatch]; + } + + function updateState(initialState) { + return updateReducer(basicStateReducer); + } + + function rerenderState(initialState) { + return rerenderReducer(basicStateReducer); + } + + function mountOptimistic(passthrough, reducer) { + var hook = mountWorkInProgressHook(); + hook.memoizedState = hook.baseState = passthrough; + var queue = { + pending: null, + lanes: NoLanes, + dispatch: null, + // Optimistic state does not use the eager update optimization. + lastRenderedReducer: null, + lastRenderedState: null + }; + hook.queue = queue; // This is different than the normal setState function. + + var dispatch = dispatchOptimisticSetState.bind( + null, + currentlyRenderingFiber$1, + true, + queue + ); + queue.dispatch = dispatch; + return [passthrough, dispatch]; + } + + function updateOptimistic(passthrough, reducer) { + var hook = updateWorkInProgressHook(); + return updateOptimisticImpl(hook, currentHook, passthrough, reducer); + } + + function updateOptimisticImpl(hook, current, passthrough, reducer) { + // Optimistic updates are always rebased on top of the latest value passed in + // as an argument. It's called a passthrough because if there are no pending + // updates, it will be returned as-is. + // + // Reset the base state to the passthrough. Future updates will be applied + // on top of this. + hook.baseState = passthrough; // If a reducer is not provided, default to the same one used by useState. + + var resolvedReducer = + typeof reducer === "function" ? reducer : basicStateReducer; + return updateReducerImpl(hook, currentHook, resolvedReducer); + } + + function rerenderOptimistic(passthrough, reducer) { + // Unlike useState, useOptimistic doesn't support render phase updates. + // Also unlike useState, we need to replay all pending updates again in case + // the passthrough value changed. + // + // So instead of a forked re-render implementation that knows how to handle + // render phase udpates, we can use the same implementation as during a + // regular mount or update. + var hook = updateWorkInProgressHook(); + + if (currentHook !== null) { + // This is an update. Process the update queue. + return updateOptimisticImpl(hook, currentHook, passthrough, reducer); + } // This is a mount. No updates to process. + // Reset the base state to the passthrough. Future updates will be applied + // on top of this. + + hook.baseState = passthrough; + var dispatch = hook.queue.dispatch; + return [passthrough, dispatch]; + } // useFormState actions run sequentially, because each action receives the + + function pushEffect(tag, create, inst, deps) { + var effect = { + tag: tag, + create: create, + inst: inst, + deps: deps, + // Circular + next: null + }; + var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; + + if (componentUpdateQueue === null) { + componentUpdateQueue = createFunctionComponentUpdateQueue(); + currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; + componentUpdateQueue.lastEffect = effect.next = effect; + } else { + var lastEffect = componentUpdateQueue.lastEffect; + + if (lastEffect === null) { + componentUpdateQueue.lastEffect = effect.next = effect; + } else { + var firstEffect = lastEffect.next; + lastEffect.next = effect; + effect.next = firstEffect; + componentUpdateQueue.lastEffect = effect; + } + } + + return effect; + } + + function createEffectInstance() { + return { + destroy: undefined + }; + } + + var stackContainsErrorMessage = null; + + function getCallerStackFrame() { + // eslint-disable-next-line react-internal/prod-error-codes + var stackFrames = new Error("Error message").stack.split("\n"); // Some browsers (e.g. Chrome) include the error message in the stack + // but others (e.g. Firefox) do not. + + if (stackContainsErrorMessage === null) { + stackContainsErrorMessage = stackFrames[0].includes("Error message"); + } + + return stackContainsErrorMessage + ? stackFrames.slice(3, 4).join("\n") + : stackFrames.slice(2, 3).join("\n"); + } + + function mountRef(initialValue) { + var hook = mountWorkInProgressHook(); + + if (enableUseRefAccessWarning) { + { + // Support lazy initialization pattern shown in docs. + // We need to store the caller stack frame so that we don't warn on subsequent renders. + var hasBeenInitialized = initialValue != null; + var lazyInitGetterStack = null; + var didCheckForLazyInit = false; // Only warn once per component+hook. + + var didWarnAboutRead = false; + var didWarnAboutWrite = false; + var current = initialValue; + var ref = { + get current() { + if (!hasBeenInitialized) { + didCheckForLazyInit = true; + lazyInitGetterStack = getCallerStackFrame(); + } else if ( + currentlyRenderingFiber$1 !== null && + !didWarnAboutRead + ) { + if ( + lazyInitGetterStack === null || + lazyInitGetterStack !== getCallerStackFrame() + ) { + didWarnAboutRead = true; + + warn( + "%s: Unsafe read of a mutable value during render.\n\n" + + "Reading from a ref during render is only safe if:\n" + + "1. The ref value has not been updated, or\n" + + "2. The ref holds a lazily-initialized value that is only set once.\n", + getComponentNameFromFiber(currentlyRenderingFiber$1) || + "Unknown" + ); + } + } + + return current; + }, + + set current(value) { + if (currentlyRenderingFiber$1 !== null && !didWarnAboutWrite) { + if (hasBeenInitialized || !didCheckForLazyInit) { + didWarnAboutWrite = true; + + warn( + "%s: Unsafe write of a mutable value during render.\n\n" + + "Writing to a ref during render is only safe if the ref holds " + + "a lazily-initialized value that is only set once.\n", + getComponentNameFromFiber(currentlyRenderingFiber$1) || + "Unknown" + ); + } + } + + hasBeenInitialized = true; + current = value; + } + }; + Object.seal(ref); + hook.memoizedState = ref; + return ref; + } + } else { + var _ref2 = { + current: initialValue + }; + hook.memoizedState = _ref2; + return _ref2; + } + } + + function updateRef(initialValue) { + var hook = updateWorkInProgressHook(); + return hook.memoizedState; + } + + function mountEffectImpl(fiberFlags, hookFlags, create, deps) { + var hook = mountWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + currentlyRenderingFiber$1.flags |= fiberFlags; + hook.memoizedState = pushEffect( + HasEffect | hookFlags, + create, + createEffectInstance(), + nextDeps + ); + } + + function updateEffectImpl(fiberFlags, hookFlags, create, deps) { + var hook = updateWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var effect = hook.memoizedState; + var inst = effect.inst; // currentHook is null on initial mount when rerendering after a render phase + // state update or for strict mode. + + if (currentHook !== null) { + if (nextDeps !== null) { + var prevEffect = currentHook.memoizedState; + var prevDeps = prevEffect.deps; + + if (areHookInputsEqual(nextDeps, prevDeps)) { + hook.memoizedState = pushEffect(hookFlags, create, inst, nextDeps); + return; + } + } + } + + currentlyRenderingFiber$1.flags |= fiberFlags; + hook.memoizedState = pushEffect( + HasEffect | hookFlags, + create, + inst, + nextDeps + ); + } + + function mountEffect(create, deps) { + if ( + (currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode && + (currentlyRenderingFiber$1.mode & NoStrictPassiveEffectsMode) === NoMode + ) { + mountEffectImpl( + MountPassiveDev | Passive$1 | PassiveStatic, + Passive, + create, + deps + ); + } else { + mountEffectImpl(Passive$1 | PassiveStatic, Passive, create, deps); + } + } + + function updateEffect(create, deps) { + updateEffectImpl(Passive$1, Passive, create, deps); + } + + function useEffectEventImpl(payload) { + currentlyRenderingFiber$1.flags |= Update; + var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; + + if (componentUpdateQueue === null) { + componentUpdateQueue = createFunctionComponentUpdateQueue(); + currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; + componentUpdateQueue.events = [payload]; + } else { + var events = componentUpdateQueue.events; + + if (events === null) { + componentUpdateQueue.events = [payload]; + } else { + events.push(payload); + } + } + } + + function mountEvent(callback) { + var hook = mountWorkInProgressHook(); + var ref = { + impl: callback + }; + hook.memoizedState = ref; // $FlowIgnore[incompatible-return] + + return function eventFn() { + if (isInvalidExecutionContextForEventFunction()) { + throw new Error( + "A function wrapped in useEffectEvent can't be called during rendering." + ); + } + + return ref.impl.apply(undefined, arguments); + }; + } + + function updateEvent(callback) { + var hook = updateWorkInProgressHook(); + var ref = hook.memoizedState; + useEffectEventImpl({ + ref: ref, + nextImpl: callback + }); // $FlowIgnore[incompatible-return] + + return function eventFn() { + if (isInvalidExecutionContextForEventFunction()) { + throw new Error( + "A function wrapped in useEffectEvent can't be called during rendering." + ); + } + + return ref.impl.apply(undefined, arguments); + }; + } + + function mountInsertionEffect(create, deps) { + mountEffectImpl(Update, Insertion, create, deps); + } + + function updateInsertionEffect(create, deps) { + return updateEffectImpl(Update, Insertion, create, deps); + } + + function mountLayoutEffect(create, deps) { + var fiberFlags = Update | LayoutStatic; + + if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { + fiberFlags |= MountLayoutDev; + } + + return mountEffectImpl(fiberFlags, Layout, create, deps); + } + + function updateLayoutEffect(create, deps) { + return updateEffectImpl(Update, Layout, create, deps); + } + + function imperativeHandleEffect(create, ref) { + if (typeof ref === "function") { + var refCallback = ref; + var inst = create(); + refCallback(inst); + return function () { + refCallback(null); + }; + } else if (ref !== null && ref !== undefined) { + var refObject = ref; + + { + if (!refObject.hasOwnProperty("current")) { + 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(", ") + "}" + ); + } + } + + var _inst = create(); + + refObject.current = _inst; + return function () { + refObject.current = null; + }; + } + } + + function mountImperativeHandle(ref, create, deps) { + { + if (typeof create !== "function") { + error( + "Expected useImperativeHandle() second argument to be a function " + + "that creates a handle. Instead received: %s.", + create !== null ? typeof create : "null" + ); + } + } // TODO: If deps are provided, should we skip comparing the ref itself? + + var effectDeps = + deps !== null && deps !== undefined ? deps.concat([ref]) : null; + var fiberFlags = Update | LayoutStatic; + + if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { + fiberFlags |= MountLayoutDev; + } + + mountEffectImpl( + fiberFlags, + Layout, + imperativeHandleEffect.bind(null, create, ref), + effectDeps + ); + } + + function updateImperativeHandle(ref, create, deps) { + { + if (typeof create !== "function") { + error( + "Expected useImperativeHandle() second argument to be a function " + + "that creates a handle. Instead received: %s.", + create !== null ? typeof create : "null" + ); + } + } // TODO: If deps are provided, should we skip comparing the ref itself? + + var effectDeps = + deps !== null && deps !== undefined ? deps.concat([ref]) : null; + updateEffectImpl( + Update, + Layout, + imperativeHandleEffect.bind(null, create, ref), + effectDeps + ); + } + + function mountDebugValue(value, formatterFn) { + // This hook is normally a no-op. + // The react-debug-hooks package injects its own implementation + // so that e.g. DevTools can display custom hook values. + } + + var updateDebugValue = mountDebugValue; + + function mountCallback(callback, deps) { + var hook = mountWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + hook.memoizedState = [callback, nextDeps]; + return callback; + } + + function updateCallback(callback, deps) { + var hook = updateWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var prevState = hook.memoizedState; + + if (nextDeps !== null) { + var prevDeps = prevState[1]; + + if (areHookInputsEqual(nextDeps, prevDeps)) { + return prevState[0]; + } + } + + hook.memoizedState = [callback, nextDeps]; + return callback; + } + + function mountMemo(nextCreate, deps) { + var hook = mountWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + + if (shouldDoubleInvokeUserFnsInHooksDEV) { + nextCreate(); + } + + var nextValue = nextCreate(); + hook.memoizedState = [nextValue, nextDeps]; + return nextValue; + } + + function updateMemo(nextCreate, deps) { + var hook = updateWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + var prevState = hook.memoizedState; // Assume these are defined. If they're not, areHookInputsEqual will warn. + + if (nextDeps !== null) { + var prevDeps = prevState[1]; + + if (areHookInputsEqual(nextDeps, prevDeps)) { + return prevState[0]; + } + } + + if (shouldDoubleInvokeUserFnsInHooksDEV) { + nextCreate(); + } + + var nextValue = nextCreate(); + hook.memoizedState = [nextValue, nextDeps]; + return nextValue; + } + + function mountDeferredValue(value, initialValue) { + var hook = mountWorkInProgressHook(); + return mountDeferredValueImpl(hook, value, initialValue); + } + + function updateDeferredValue(value, initialValue) { + var hook = updateWorkInProgressHook(); + var resolvedCurrentHook = currentHook; + var prevValue = resolvedCurrentHook.memoizedState; + return updateDeferredValueImpl(hook, prevValue, value, initialValue); + } + + function rerenderDeferredValue(value, initialValue) { + var hook = updateWorkInProgressHook(); + + if (currentHook === null) { + // This is a rerender during a mount. + return mountDeferredValueImpl(hook, value, initialValue); + } else { + // This is a rerender during an update. + var prevValue = currentHook.memoizedState; + return updateDeferredValueImpl(hook, prevValue, value, initialValue); + } + } + + function mountDeferredValueImpl(hook, value, initialValue) { + if ( + enableUseDeferredValueInitialArg && // When `initialValue` is provided, we defer the initial render even if the + // current render is not synchronous. + initialValue !== undefined && // However, to avoid waterfalls, we do not defer if this render + // was itself spawned by an earlier useDeferredValue. Check if DeferredLane + // is part of the render lanes. + !includesSomeLane(renderLanes, DeferredLane) + ) { + // Render with the initial value + hook.memoizedState = initialValue; // Schedule a deferred render to switch to the final value. + + var deferredLane = requestDeferredLane(); + currentlyRenderingFiber$1.lanes = mergeLanes( + currentlyRenderingFiber$1.lanes, + deferredLane + ); + markSkippedUpdateLanes(deferredLane); + return initialValue; + } else { + hook.memoizedState = value; + return value; + } + } + + function updateDeferredValueImpl(hook, prevValue, value, initialValue) { + if (objectIs(value, prevValue)) { + // The incoming value is referentially identical to the currently rendered + // value, so we can bail out quickly. + return value; + } else { + // Received a new value that's different from the current value. + // Check if we're inside a hidden tree + if (isCurrentTreeHidden()) { + // Revealing a prerendered tree is considered the same as mounting new + // one, so we reuse the "mount" path in this case. + var resultValue = mountDeferredValueImpl(hook, value, initialValue); // Unlike during an actual mount, we need to mark this as an update if + // the value changed. + + if (!objectIs(resultValue, prevValue)) { + markWorkInProgressReceivedUpdate(); + } + + return resultValue; + } + + var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes); + + if (shouldDeferValue) { + // This is an urgent update. Since the value has changed, keep using the + // previous value and spawn a deferred render to update it later. + // Schedule a deferred render + var deferredLane = requestDeferredLane(); + currentlyRenderingFiber$1.lanes = mergeLanes( + currentlyRenderingFiber$1.lanes, + deferredLane + ); + markSkippedUpdateLanes(deferredLane); // Reuse the previous value. We do not need to mark this as an update, + // because we did not render a new value. + + return prevValue; + } else { + // This is not an urgent update, so we can use the latest value regardless + // of what it is. No need to defer it. + // Mark this as an update to prevent the fiber from bailing out. + markWorkInProgressReceivedUpdate(); + hook.memoizedState = value; + return value; + } + } + } + + function startTransition( + fiber, + queue, + pendingState, + finishedState, + callback, + options + ) { + var previousPriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority( + higherEventPriority(previousPriority, ContinuousEventPriority) + ); + var prevTransition = ReactCurrentBatchConfig$2.transition; + var currentTransition = {}; + + if (enableAsyncActions) { + // We don't really need to use an optimistic update here, because we + // schedule a second "revert" update below (which we use to suspend the + // transition until the async action scope has finished). But we'll use an + // optimistic update anyway to make it less likely the behavior accidentally + // diverges; for example, both an optimistic update and this one should + // share the same lane. + ReactCurrentBatchConfig$2.transition = currentTransition; + dispatchOptimisticSetState(fiber, false, queue, pendingState); + } else { + ReactCurrentBatchConfig$2.transition = null; + dispatchSetState(fiber, queue, pendingState); + ReactCurrentBatchConfig$2.transition = currentTransition; + } + + if (enableTransitionTracing) { + if (options !== undefined && options.name !== undefined) { + ReactCurrentBatchConfig$2.transition.name = options.name; + ReactCurrentBatchConfig$2.transition.startTime = now$1(); + } + } + + { + ReactCurrentBatchConfig$2.transition._updatedFibers = new Set(); + } + + try { + if (enableAsyncActions) { + var returnValue = callback(); // Check if we're inside an async action scope. If so, we'll entangle + // this new action with the existing scope. + // + // If we're not already inside an async action scope, and this action is + // async, then we'll create a new async scope. + // + // In the async case, the resulting render will suspend until the async + // action scope has finished. + + if ( + returnValue !== null && + typeof returnValue === "object" && + typeof returnValue.then === "function" + ) { + var thenable = returnValue; // This is a thenable that resolves to `finishedState` once the async + // action scope has finished. + + var entangledResult = requestAsyncActionContext( + thenable, + finishedState + ); + dispatchSetState(fiber, queue, entangledResult); + } else { + // This is either `finishedState` or a thenable that resolves to + // `finishedState`, depending on whether we're inside an async + // action scope. + var _entangledResult2 = requestSyncActionContext( + returnValue, + finishedState + ); + + dispatchSetState(fiber, queue, _entangledResult2); + } + } else { + // Async actions are not enabled. + dispatchSetState(fiber, queue, finishedState); + callback(); + } + } catch (error) { + if (enableAsyncActions) { + // This is a trick to get the `useTransition` hook to rethrow the error. + // When it unwraps the thenable with the `use` algorithm, the error + // will be thrown. + var rejectedThenable = { + then: function () {}, + status: "rejected", + reason: error + }; + dispatchSetState(fiber, queue, rejectedThenable); + } else { + // The error rethrowing behavior is only enabled when the async actions + // feature is on, even for sync actions. + throw error; + } + } finally { + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig$2.transition = prevTransition; + + { + if (prevTransition === null && currentTransition._updatedFibers) { + var updatedFibersCount = currentTransition._updatedFibers.size; + + currentTransition._updatedFibers.clear(); + + if (updatedFibersCount > 10) { + 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." + ); + } + } + } + } + } + + function mountTransition() { + var stateHook = mountStateImpl(false); // The `start` method never changes. + + var start = startTransition.bind( + null, + currentlyRenderingFiber$1, + stateHook.queue, + true, + false + ); + var hook = mountWorkInProgressHook(); + hook.memoizedState = start; + return [false, start]; + } + + function updateTransition() { + var _updateState = updateState(), + booleanOrThenable = _updateState[0]; + + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; + var isPending = + typeof booleanOrThenable === "boolean" + ? booleanOrThenable // This will suspend until the async action scope has finished. + : useThenable(booleanOrThenable); + return [isPending, start]; + } + + function rerenderTransition() { + var _rerenderState = rerenderState(), + booleanOrThenable = _rerenderState[0]; + + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; + var isPending = + typeof booleanOrThenable === "boolean" + ? booleanOrThenable // This will suspend until the async action scope has finished. + : useThenable(booleanOrThenable); + return [isPending, start]; + } + + function mountId() { + var hook = mountWorkInProgressHook(); + var root = getWorkInProgressRoot(); // TODO: In Fizz, id generation is specific to each server config. Maybe we + // should do this in Fiber, too? Deferring this decision for now because + // there's no other place to store the prefix except for an internal field on + // the public createRoot object, which the fiber tree does not currently have + // a reference to. + + var identifierPrefix = root.identifierPrefix; + var id; + + { + // Use a lowercase r prefix for client-generated ids. + var globalClientId = globalClientIdCounter++; + id = ":" + identifierPrefix + "r" + globalClientId.toString(32) + ":"; + } + + hook.memoizedState = id; + return id; + } + + function updateId() { + var hook = updateWorkInProgressHook(); + var id = hook.memoizedState; + return id; + } + + function mountRefresh() { + var hook = mountWorkInProgressHook(); + var refresh = (hook.memoizedState = refreshCache.bind( + null, + currentlyRenderingFiber$1 + )); + return refresh; + } + + function updateRefresh() { + var hook = updateWorkInProgressHook(); + return hook.memoizedState; + } + + function refreshCache(fiber, seedKey, seedValue) { + // TODO: Consider warning if the refresh is at discrete priority, or if we + // otherwise suspect that it wasn't batched properly. + + var provider = fiber.return; + + while (provider !== null) { + switch (provider.tag) { + case CacheComponent: + case HostRoot: { + // Schedule an update on the cache boundary to trigger a refresh. + var lane = requestUpdateLane(provider); + var refreshUpdate = createUpdate(lane); + var root = enqueueUpdate(provider, refreshUpdate, lane); + + if (root !== null) { + scheduleUpdateOnFiber(root, provider, lane); + entangleTransitions(root, provider, lane); + } // TODO: If a refresh never commits, the new cache created here must be + // released. A simple case is start refreshing a cache boundary, but then + // unmount that boundary before the refresh completes. + + var seededCache = createCache(); + + if (seedKey !== null && seedKey !== undefined && root !== null) { + { + // Seed the cache with the value passed by the caller. This could be + // from a server mutation, or it could be a streaming response. + seededCache.data.set(seedKey, seedValue); + } + } + + var payload = { + cache: seededCache + }; + refreshUpdate.payload = payload; + return; + } + } + + provider = provider.return; + } // TODO: Warn if unmounted? + } + + function dispatchReducerAction(fiber, queue, action) { + { + if (typeof arguments[3] === "function") { + 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()." + ); + } + } + + var lane = requestUpdateLane(fiber); + var update = { + lane: lane, + revertLane: NoLane, + action: action, + hasEagerState: false, + eagerState: null, + next: null + }; + + if (isRenderPhaseUpdate(fiber)) { + enqueueRenderPhaseUpdate(queue, update); + } else { + var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); + + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane); + entangleTransitionUpdate(root, queue, lane); + } + } + + markUpdateInDevTools(fiber, lane, action); + } + + function dispatchSetState(fiber, queue, action) { + { + if (typeof arguments[3] === "function") { + 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()." + ); + } + } + + var lane = requestUpdateLane(fiber); + var update = { + lane: lane, + revertLane: NoLane, + action: action, + hasEagerState: false, + eagerState: null, + next: null + }; + + if (isRenderPhaseUpdate(fiber)) { + enqueueRenderPhaseUpdate(queue, update); + } else { + var alternate = fiber.alternate; + + if ( + fiber.lanes === NoLanes && + (alternate === null || alternate.lanes === NoLanes) + ) { + // The queue is currently empty, which means we can eagerly compute the + // next state before entering the render phase. If the new state is the + // same as the current state, we may be able to bail out entirely. + var lastRenderedReducer = queue.lastRenderedReducer; + + if (lastRenderedReducer !== null) { + var prevDispatcher; + + { + prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + } + + try { + var currentState = queue.lastRenderedState; + var eagerState = lastRenderedReducer(currentState, action); // Stash the eagerly computed state, and the reducer used to compute + // it, on the update object. If the reducer hasn't changed by the + // time we enter the render phase, then the eager state can be used + // without calling the reducer again. + + update.hasEagerState = true; + update.eagerState = eagerState; + + if (objectIs(eagerState, currentState)) { + // Fast path. We can bail out without scheduling React to re-render. + // It's still possible that we'll need to rebase this update later, + // if the component re-renders for a different reason and by that + // time the reducer has changed. + // TODO: Do we still need to entangle transitions in this case? + enqueueConcurrentHookUpdateAndEagerlyBailout( + fiber, + queue, + update + ); + return; + } + } catch (error) { + // Suppress the error. It will throw again in the render phase. + } finally { + { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + } + } + } + + var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); + + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane); + entangleTransitionUpdate(root, queue, lane); + } + } + + markUpdateInDevTools(fiber, lane, action); + } + + function dispatchOptimisticSetState( + fiber, + throwIfDuringRender, + queue, + action + ) { + { + if (ReactCurrentBatchConfig$2.transition === null) { + // An optimistic update occurred, but startTransition is not on the stack. + // There are two likely scenarios. + // One possibility is that the optimistic update is triggered by a regular + // event handler (e.g. `onSubmit`) instead of an action. This is a mistake + // and we will warn. + // The other possibility is the optimistic update is inside an async + // action, but after an `await`. In this case, we can make it "just work" + // by associating the optimistic update with the pending async action. + // Technically it's possible that the optimistic update is unrelated to + // the pending action, but we don't have a way of knowing this for sure + // because browsers currently do not provide a way to track async scope. + // (The AsyncContext proposal, if it lands, will solve this in the + // future.) However, this is no different than the problem of unrelated + // transitions being grouped together — it's not wrong per se, but it's + // not ideal. + // Once AsyncContext starts landing in browsers, we will provide better + // warnings in development for these cases. + if (peekEntangledActionLane() !== NoLane); + else { + // There's no pending async action. The most likely cause is that we're + // inside a regular event handler (e.g. onSubmit) instead of an action. + error( + "An optimistic state update occurred outside a transition or " + + "action. To fix, move the update to an action, or wrap " + + "with startTransition." + ); + } + } + } + + var update = { + // An optimistic update commits synchronously. + lane: SyncLane, + // After committing, the optimistic update is "reverted" using the same + // lane as the transition it's associated with. + revertLane: requestTransitionLane(), + action: action, + hasEagerState: false, + eagerState: null, + next: null + }; + + if (isRenderPhaseUpdate(fiber)) { + // When calling startTransition during render, this warns instead of + // throwing because throwing would be a breaking change. setOptimisticState + // is a new API so it's OK to throw. + if (throwIfDuringRender) { + throw new Error("Cannot update optimistic state while rendering."); + } else { + // startTransition was called during render. We don't need to do anything + // besides warn here because the render phase update would be overidden by + // the second update, anyway. We can remove this branch and make it throw + // in a future release. + { + error("Cannot call startTransition while rendering."); + } + } + } else { + var root = enqueueConcurrentHookUpdate(fiber, queue, update, SyncLane); + + if (root !== null) { + // NOTE: The optimistic update implementation assumes that the transition + // will never be attempted before the optimistic update. This currently + // holds because the optimistic update is always synchronous. If we ever + // change that, we'll need to account for this. + scheduleUpdateOnFiber(root, fiber, SyncLane); // Optimistic updates are always synchronous, so we don't need to call + // entangleTransitionUpdate here. + } + } + + markUpdateInDevTools(fiber, SyncLane, action); + } + + function isRenderPhaseUpdate(fiber) { + var alternate = fiber.alternate; + return ( + fiber === currentlyRenderingFiber$1 || + (alternate !== null && alternate === currentlyRenderingFiber$1) + ); + } + + function enqueueRenderPhaseUpdate(queue, update) { + // This is a render phase update. Stash it in a lazily-created map of + // queue -> linked list of updates. After this render pass, we'll restart + // and apply the stashed updates on top of the work-in-progress hook. + didScheduleRenderPhaseUpdateDuringThisPass = + didScheduleRenderPhaseUpdate = true; + var pending = queue.pending; + + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; + } + + queue.pending = update; + } // TODO: Move to ReactFiberConcurrentUpdates? + + function entangleTransitionUpdate(root, queue, lane) { + if (isTransitionLane(lane)) { + var queueLanes = queue.lanes; // If any entangled lanes are no longer pending on the root, then they + // must have finished. We can remove them from the shared queue, which + // represents a superset of the actually pending lanes. In some cases we + // may entangle more than we need to, but that's OK. In fact it's worse if + // we *don't* entangle when we should. + + queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. + + var newQueueLanes = mergeLanes(queueLanes, lane); + queue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if + // the lane finished since the last time we entangled it. So we need to + // entangle it again, just to be sure. + + markRootEntangled(root, newQueueLanes); + } + } + + function markUpdateInDevTools(fiber, lane, action) { + { + if (enableDebugTracing) { + if (fiber.mode & DebugTracingMode) { + var name = getComponentNameFromFiber(fiber) || "Unknown"; + logStateUpdateScheduled(name, lane, action); + } + } + } + + if (enableSchedulingProfiler) { + markStateUpdateScheduled(fiber, lane); + } + } + + var ContextOnlyDispatcher = { + readContext: readContext, + use: use, + useCallback: throwInvalidHookError, + useContext: throwInvalidHookError, + useEffect: throwInvalidHookError, + useImperativeHandle: throwInvalidHookError, + useInsertionEffect: throwInvalidHookError, + useLayoutEffect: throwInvalidHookError, + useMemo: throwInvalidHookError, + useReducer: throwInvalidHookError, + useRef: throwInvalidHookError, + useState: throwInvalidHookError, + useDebugValue: throwInvalidHookError, + useDeferredValue: throwInvalidHookError, + useTransition: throwInvalidHookError, + useSyncExternalStore: throwInvalidHookError, + useId: throwInvalidHookError + }; + + { + ContextOnlyDispatcher.useCacheRefresh = throwInvalidHookError; + } + + { + ContextOnlyDispatcher.useMemoCache = throwInvalidHookError; + } + + { + ContextOnlyDispatcher.useEffectEvent = throwInvalidHookError; + } + + if (enableAsyncActions) { + ContextOnlyDispatcher.useOptimistic = throwInvalidHookError; + } + + var HooksDispatcherOnMountInDEV = null; + var HooksDispatcherOnMountWithHookTypesInDEV = null; + var HooksDispatcherOnUpdateInDEV = null; + var HooksDispatcherOnRerenderInDEV = null; + var InvalidNestedHooksDispatcherOnMountInDEV = null; + var InvalidNestedHooksDispatcherOnUpdateInDEV = null; + var InvalidNestedHooksDispatcherOnRerenderInDEV = null; + + { + var warnInvalidContextAccess = function () { + 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()." + ); + }; + + var warnInvalidHookAccess = function () { + 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" + ); + }; + + HooksDispatcherOnMountInDEV = { + readContext: function (context) { + return readContext(context); + }, + use: use, + useCallback: function (callback, deps) { + currentHookNameInDev = "useCallback"; + mountHookTypesDev(); + checkDepsAreArrayDev(deps); + return mountCallback(callback, deps); + }, + useContext: function (context) { + currentHookNameInDev = "useContext"; + mountHookTypesDev(); + return readContext(context); + }, + useEffect: function (create, deps) { + currentHookNameInDev = "useEffect"; + mountHookTypesDev(); + checkDepsAreArrayDev(deps); + return mountEffect(create, deps); + }, + useImperativeHandle: function (ref, create, deps) { + currentHookNameInDev = "useImperativeHandle"; + mountHookTypesDev(); + checkDepsAreArrayDev(deps); + return mountImperativeHandle(ref, create, deps); + }, + useInsertionEffect: function (create, deps) { + currentHookNameInDev = "useInsertionEffect"; + mountHookTypesDev(); + checkDepsAreArrayDev(deps); + return mountInsertionEffect(create, deps); + }, + useLayoutEffect: function (create, deps) { + currentHookNameInDev = "useLayoutEffect"; + mountHookTypesDev(); + checkDepsAreArrayDev(deps); + return mountLayoutEffect(create, deps); + }, + useMemo: function (create, deps) { + currentHookNameInDev = "useMemo"; + mountHookTypesDev(); + checkDepsAreArrayDev(deps); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountMemo(create, deps); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useReducer: function (reducer, initialArg, init) { + currentHookNameInDev = "useReducer"; + mountHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountReducer(reducer, initialArg, init); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useRef: function (initialValue) { + currentHookNameInDev = "useRef"; + mountHookTypesDev(); + return mountRef(initialValue); + }, + useState: function (initialState) { + currentHookNameInDev = "useState"; + mountHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + mountHookTypesDev(); + return mountDebugValue(); + }, + useDeferredValue: function (value, initialValue) { + currentHookNameInDev = "useDeferredValue"; + mountHookTypesDev(); + return mountDeferredValue(value, initialValue); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + mountHookTypesDev(); + return mountTransition(); + }, + useSyncExternalStore: function ( + subscribe, + getSnapshot, + getServerSnapshot + ) { + currentHookNameInDev = "useSyncExternalStore"; + mountHookTypesDev(); + return mountSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + mountHookTypesDev(); + return mountId(); + } + }; + + { + HooksDispatcherOnMountInDEV.useCacheRefresh = + function useCacheRefresh() { + currentHookNameInDev = "useCacheRefresh"; + mountHookTypesDev(); + return mountRefresh(); + }; + } + + { + HooksDispatcherOnMountInDEV.useMemoCache = useMemoCache; + } + + { + HooksDispatcherOnMountInDEV.useEffectEvent = function useEffectEvent( + callback + ) { + currentHookNameInDev = "useEffectEvent"; + mountHookTypesDev(); + return mountEvent(callback); + }; + } + + if (enableAsyncActions) { + HooksDispatcherOnMountInDEV.useOptimistic = function useOptimistic( + passthrough, + reducer + ) { + currentHookNameInDev = "useOptimistic"; + mountHookTypesDev(); + return mountOptimistic(passthrough); + }; + } + + HooksDispatcherOnMountWithHookTypesInDEV = { + readContext: function (context) { + return readContext(context); + }, + use: use, + useCallback: function (callback, deps) { + currentHookNameInDev = "useCallback"; + updateHookTypesDev(); + return mountCallback(callback, deps); + }, + useContext: function (context) { + currentHookNameInDev = "useContext"; + updateHookTypesDev(); + return readContext(context); + }, + useEffect: function (create, deps) { + currentHookNameInDev = "useEffect"; + updateHookTypesDev(); + return mountEffect(create, deps); + }, + useImperativeHandle: function (ref, create, deps) { + currentHookNameInDev = "useImperativeHandle"; + updateHookTypesDev(); + return mountImperativeHandle(ref, create, deps); + }, + useInsertionEffect: function (create, deps) { + currentHookNameInDev = "useInsertionEffect"; + updateHookTypesDev(); + return mountInsertionEffect(create, deps); + }, + useLayoutEffect: function (create, deps) { + currentHookNameInDev = "useLayoutEffect"; + updateHookTypesDev(); + return mountLayoutEffect(create, deps); + }, + useMemo: function (create, deps) { + currentHookNameInDev = "useMemo"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountMemo(create, deps); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useReducer: function (reducer, initialArg, init) { + currentHookNameInDev = "useReducer"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountReducer(reducer, initialArg, init); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useRef: function (initialValue) { + currentHookNameInDev = "useRef"; + updateHookTypesDev(); + return mountRef(initialValue); + }, + useState: function (initialState) { + currentHookNameInDev = "useState"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + updateHookTypesDev(); + return mountDebugValue(); + }, + useDeferredValue: function (value, initialValue) { + currentHookNameInDev = "useDeferredValue"; + updateHookTypesDev(); + return mountDeferredValue(value, initialValue); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + updateHookTypesDev(); + return mountTransition(); + }, + useSyncExternalStore: function ( + subscribe, + getSnapshot, + getServerSnapshot + ) { + currentHookNameInDev = "useSyncExternalStore"; + updateHookTypesDev(); + return mountSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + updateHookTypesDev(); + return mountId(); + } + }; + + { + HooksDispatcherOnMountWithHookTypesInDEV.useCacheRefresh = + function useCacheRefresh() { + currentHookNameInDev = "useCacheRefresh"; + updateHookTypesDev(); + return mountRefresh(); + }; + } + + { + HooksDispatcherOnMountWithHookTypesInDEV.useMemoCache = useMemoCache; + } + + { + HooksDispatcherOnMountWithHookTypesInDEV.useEffectEvent = + function useEffectEvent(callback) { + currentHookNameInDev = "useEffectEvent"; + updateHookTypesDev(); + return mountEvent(callback); + }; + } + + if (enableAsyncActions) { + HooksDispatcherOnMountWithHookTypesInDEV.useOptimistic = + function useOptimistic(passthrough, reducer) { + currentHookNameInDev = "useOptimistic"; + updateHookTypesDev(); + return mountOptimistic(passthrough); + }; + } + + HooksDispatcherOnUpdateInDEV = { + readContext: function (context) { + return readContext(context); + }, + use: use, + useCallback: function (callback, deps) { + currentHookNameInDev = "useCallback"; + updateHookTypesDev(); + return updateCallback(callback, deps); + }, + useContext: function (context) { + currentHookNameInDev = "useContext"; + updateHookTypesDev(); + return readContext(context); + }, + useEffect: function (create, deps) { + currentHookNameInDev = "useEffect"; + updateHookTypesDev(); + return updateEffect(create, deps); + }, + useImperativeHandle: function (ref, create, deps) { + currentHookNameInDev = "useImperativeHandle"; + updateHookTypesDev(); + return updateImperativeHandle(ref, create, deps); + }, + useInsertionEffect: function (create, deps) { + currentHookNameInDev = "useInsertionEffect"; + updateHookTypesDev(); + return updateInsertionEffect(create, deps); + }, + useLayoutEffect: function (create, deps) { + currentHookNameInDev = "useLayoutEffect"; + updateHookTypesDev(); + return updateLayoutEffect(create, deps); + }, + useMemo: function (create, deps) { + currentHookNameInDev = "useMemo"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return updateMemo(create, deps); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useReducer: function (reducer, initialArg, init) { + currentHookNameInDev = "useReducer"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return updateReducer(reducer, initialArg, init); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useRef: function (initialValue) { + currentHookNameInDev = "useRef"; + updateHookTypesDev(); + return updateRef(); + }, + useState: function (initialState) { + currentHookNameInDev = "useState"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return updateState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + updateHookTypesDev(); + return updateDebugValue(); + }, + useDeferredValue: function (value, initialValue) { + currentHookNameInDev = "useDeferredValue"; + updateHookTypesDev(); + return updateDeferredValue(value, initialValue); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + updateHookTypesDev(); + return updateTransition(); + }, + useSyncExternalStore: function ( + subscribe, + getSnapshot, + getServerSnapshot + ) { + currentHookNameInDev = "useSyncExternalStore"; + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + updateHookTypesDev(); + return updateId(); + } + }; + + { + HooksDispatcherOnUpdateInDEV.useCacheRefresh = + function useCacheRefresh() { + currentHookNameInDev = "useCacheRefresh"; + updateHookTypesDev(); + return updateRefresh(); + }; + } + + { + HooksDispatcherOnUpdateInDEV.useMemoCache = useMemoCache; + } + + { + HooksDispatcherOnUpdateInDEV.useEffectEvent = function useEffectEvent( + callback + ) { + currentHookNameInDev = "useEffectEvent"; + updateHookTypesDev(); + return updateEvent(callback); + }; + } + + if (enableAsyncActions) { + HooksDispatcherOnUpdateInDEV.useOptimistic = function useOptimistic( + passthrough, + reducer + ) { + currentHookNameInDev = "useOptimistic"; + updateHookTypesDev(); + return updateOptimistic(passthrough, reducer); + }; + } + + HooksDispatcherOnRerenderInDEV = { + readContext: function (context) { + return readContext(context); + }, + use: use, + useCallback: function (callback, deps) { + currentHookNameInDev = "useCallback"; + updateHookTypesDev(); + return updateCallback(callback, deps); + }, + useContext: function (context) { + currentHookNameInDev = "useContext"; + updateHookTypesDev(); + return readContext(context); + }, + useEffect: function (create, deps) { + currentHookNameInDev = "useEffect"; + updateHookTypesDev(); + return updateEffect(create, deps); + }, + useImperativeHandle: function (ref, create, deps) { + currentHookNameInDev = "useImperativeHandle"; + updateHookTypesDev(); + return updateImperativeHandle(ref, create, deps); + }, + useInsertionEffect: function (create, deps) { + currentHookNameInDev = "useInsertionEffect"; + updateHookTypesDev(); + return updateInsertionEffect(create, deps); + }, + useLayoutEffect: function (create, deps) { + currentHookNameInDev = "useLayoutEffect"; + updateHookTypesDev(); + return updateLayoutEffect(create, deps); + }, + useMemo: function (create, deps) { + currentHookNameInDev = "useMemo"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnRerenderInDEV; + + try { + return updateMemo(create, deps); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useReducer: function (reducer, initialArg, init) { + currentHookNameInDev = "useReducer"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnRerenderInDEV; + + try { + return rerenderReducer(reducer, initialArg, init); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useRef: function (initialValue) { + currentHookNameInDev = "useRef"; + updateHookTypesDev(); + return updateRef(); + }, + useState: function (initialState) { + currentHookNameInDev = "useState"; + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnRerenderInDEV; + + try { + return rerenderState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + updateHookTypesDev(); + return updateDebugValue(); + }, + useDeferredValue: function (value, initialValue) { + currentHookNameInDev = "useDeferredValue"; + updateHookTypesDev(); + return rerenderDeferredValue(value, initialValue); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + updateHookTypesDev(); + return rerenderTransition(); + }, + useSyncExternalStore: function ( + subscribe, + getSnapshot, + getServerSnapshot + ) { + currentHookNameInDev = "useSyncExternalStore"; + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + updateHookTypesDev(); + return updateId(); + } + }; + + { + HooksDispatcherOnRerenderInDEV.useCacheRefresh = + function useCacheRefresh() { + currentHookNameInDev = "useCacheRefresh"; + updateHookTypesDev(); + return updateRefresh(); + }; + } + + { + HooksDispatcherOnRerenderInDEV.useMemoCache = useMemoCache; + } + + { + HooksDispatcherOnRerenderInDEV.useEffectEvent = function useEffectEvent( + callback + ) { + currentHookNameInDev = "useEffectEvent"; + updateHookTypesDev(); + return updateEvent(callback); + }; + } + + if (enableAsyncActions) { + HooksDispatcherOnRerenderInDEV.useOptimistic = function useOptimistic( + passthrough, + reducer + ) { + currentHookNameInDev = "useOptimistic"; + updateHookTypesDev(); + return rerenderOptimistic(passthrough, reducer); + }; + } + + InvalidNestedHooksDispatcherOnMountInDEV = { + readContext: function (context) { + warnInvalidContextAccess(); + return readContext(context); + }, + use: function (usable) { + warnInvalidHookAccess(); + return use(usable); + }, + useCallback: function (callback, deps) { + currentHookNameInDev = "useCallback"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountCallback(callback, deps); + }, + useContext: function (context) { + currentHookNameInDev = "useContext"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return readContext(context); + }, + useEffect: function (create, deps) { + currentHookNameInDev = "useEffect"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountEffect(create, deps); + }, + useImperativeHandle: function (ref, create, deps) { + currentHookNameInDev = "useImperativeHandle"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountImperativeHandle(ref, create, deps); + }, + useInsertionEffect: function (create, deps) { + currentHookNameInDev = "useInsertionEffect"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountInsertionEffect(create, deps); + }, + useLayoutEffect: function (create, deps) { + currentHookNameInDev = "useLayoutEffect"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountLayoutEffect(create, deps); + }, + useMemo: function (create, deps) { + currentHookNameInDev = "useMemo"; + warnInvalidHookAccess(); + mountHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountMemo(create, deps); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useReducer: function (reducer, initialArg, init) { + currentHookNameInDev = "useReducer"; + warnInvalidHookAccess(); + mountHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountReducer(reducer, initialArg, init); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useRef: function (initialValue) { + currentHookNameInDev = "useRef"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountRef(initialValue); + }, + useState: function (initialState) { + currentHookNameInDev = "useState"; + warnInvalidHookAccess(); + mountHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnMountInDEV; + + try { + return mountState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountDebugValue(); + }, + useDeferredValue: function (value, initialValue) { + currentHookNameInDev = "useDeferredValue"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountDeferredValue(value, initialValue); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountTransition(); + }, + useSyncExternalStore: function ( + subscribe, + getSnapshot, + getServerSnapshot + ) { + currentHookNameInDev = "useSyncExternalStore"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountId(); + } + }; + + { + InvalidNestedHooksDispatcherOnMountInDEV.useCacheRefresh = + function useCacheRefresh() { + currentHookNameInDev = "useCacheRefresh"; + mountHookTypesDev(); + return mountRefresh(); + }; + } + + { + InvalidNestedHooksDispatcherOnMountInDEV.useMemoCache = function ( + size + ) { + warnInvalidHookAccess(); + return useMemoCache(size); + }; + } + + { + InvalidNestedHooksDispatcherOnMountInDEV.useEffectEvent = + function useEffectEvent(callback) { + currentHookNameInDev = "useEffectEvent"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountEvent(callback); + }; + } + + if (enableAsyncActions) { + InvalidNestedHooksDispatcherOnMountInDEV.useOptimistic = + function useOptimistic(passthrough, reducer) { + currentHookNameInDev = "useOptimistic"; + warnInvalidHookAccess(); + mountHookTypesDev(); + return mountOptimistic(passthrough); + }; + } + + InvalidNestedHooksDispatcherOnUpdateInDEV = { + readContext: function (context) { + warnInvalidContextAccess(); + return readContext(context); + }, + use: function (usable) { + warnInvalidHookAccess(); + return use(usable); + }, + useCallback: function (callback, deps) { + currentHookNameInDev = "useCallback"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateCallback(callback, deps); + }, + useContext: function (context) { + currentHookNameInDev = "useContext"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return readContext(context); + }, + useEffect: function (create, deps) { + currentHookNameInDev = "useEffect"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateEffect(create, deps); + }, + useImperativeHandle: function (ref, create, deps) { + currentHookNameInDev = "useImperativeHandle"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateImperativeHandle(ref, create, deps); + }, + useInsertionEffect: function (create, deps) { + currentHookNameInDev = "useInsertionEffect"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateInsertionEffect(create, deps); + }, + useLayoutEffect: function (create, deps) { + currentHookNameInDev = "useLayoutEffect"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateLayoutEffect(create, deps); + }, + useMemo: function (create, deps) { + currentHookNameInDev = "useMemo"; + warnInvalidHookAccess(); + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return updateMemo(create, deps); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useReducer: function (reducer, initialArg, init) { + currentHookNameInDev = "useReducer"; + warnInvalidHookAccess(); + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return updateReducer(reducer, initialArg, init); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useRef: function (initialValue) { + currentHookNameInDev = "useRef"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateRef(); + }, + useState: function (initialState) { + currentHookNameInDev = "useState"; + warnInvalidHookAccess(); + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return updateState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateDebugValue(); + }, + useDeferredValue: function (value, initialValue) { + currentHookNameInDev = "useDeferredValue"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateDeferredValue(value, initialValue); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateTransition(); + }, + useSyncExternalStore: function ( + subscribe, + getSnapshot, + getServerSnapshot + ) { + currentHookNameInDev = "useSyncExternalStore"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateId(); + } + }; + + { + InvalidNestedHooksDispatcherOnUpdateInDEV.useCacheRefresh = + function useCacheRefresh() { + currentHookNameInDev = "useCacheRefresh"; + updateHookTypesDev(); + return updateRefresh(); + }; + } + + { + InvalidNestedHooksDispatcherOnUpdateInDEV.useMemoCache = function ( + size + ) { + warnInvalidHookAccess(); + return useMemoCache(size); + }; + } + + { + InvalidNestedHooksDispatcherOnUpdateInDEV.useEffectEvent = + function useEffectEvent(callback) { + currentHookNameInDev = "useEffectEvent"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateEvent(callback); + }; + } + + if (enableAsyncActions) { + InvalidNestedHooksDispatcherOnUpdateInDEV.useOptimistic = + function useOptimistic(passthrough, reducer) { + currentHookNameInDev = "useOptimistic"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateOptimistic(passthrough, reducer); + }; + } + + InvalidNestedHooksDispatcherOnRerenderInDEV = { + readContext: function (context) { + warnInvalidContextAccess(); + return readContext(context); + }, + use: function (usable) { + warnInvalidHookAccess(); + return use(usable); + }, + useCallback: function (callback, deps) { + currentHookNameInDev = "useCallback"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateCallback(callback, deps); + }, + useContext: function (context) { + currentHookNameInDev = "useContext"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return readContext(context); + }, + useEffect: function (create, deps) { + currentHookNameInDev = "useEffect"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateEffect(create, deps); + }, + useImperativeHandle: function (ref, create, deps) { + currentHookNameInDev = "useImperativeHandle"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateImperativeHandle(ref, create, deps); + }, + useInsertionEffect: function (create, deps) { + currentHookNameInDev = "useInsertionEffect"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateInsertionEffect(create, deps); + }, + useLayoutEffect: function (create, deps) { + currentHookNameInDev = "useLayoutEffect"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateLayoutEffect(create, deps); + }, + useMemo: function (create, deps) { + currentHookNameInDev = "useMemo"; + warnInvalidHookAccess(); + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return updateMemo(create, deps); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useReducer: function (reducer, initialArg, init) { + currentHookNameInDev = "useReducer"; + warnInvalidHookAccess(); + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return rerenderReducer(reducer, initialArg, init); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useRef: function (initialValue) { + currentHookNameInDev = "useRef"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateRef(); + }, + useState: function (initialState) { + currentHookNameInDev = "useState"; + warnInvalidHookAccess(); + updateHookTypesDev(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = + InvalidNestedHooksDispatcherOnUpdateInDEV; + + try { + return rerenderState(initialState); + } finally { + ReactCurrentDispatcher$1.current = prevDispatcher; + } + }, + useDebugValue: function (value, formatterFn) { + currentHookNameInDev = "useDebugValue"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateDebugValue(); + }, + useDeferredValue: function (value, initialValue) { + currentHookNameInDev = "useDeferredValue"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return rerenderDeferredValue(value, initialValue); + }, + useTransition: function () { + currentHookNameInDev = "useTransition"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return rerenderTransition(); + }, + useSyncExternalStore: function ( + subscribe, + getSnapshot, + getServerSnapshot + ) { + currentHookNameInDev = "useSyncExternalStore"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateSyncExternalStore(subscribe, getSnapshot); + }, + useId: function () { + currentHookNameInDev = "useId"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateId(); + } + }; - if (nextLanes === NoLane) { - // This root has no more pending work. Remove it from the schedule. To - // guard against subtle reentrancy bugs, this microtask is the only place - // we do this — you can add roots to the schedule whenever, but you can - // only remove them here. - // Null this out so we know it's been removed from the schedule. - root.next = null; + { + InvalidNestedHooksDispatcherOnRerenderInDEV.useCacheRefresh = + function useCacheRefresh() { + currentHookNameInDev = "useCacheRefresh"; + updateHookTypesDev(); + return updateRefresh(); + }; + } - if (prev === null) { - // This is the new head of the list - firstScheduledRoot = next; - } else { - prev.next = next; + { + InvalidNestedHooksDispatcherOnRerenderInDEV.useMemoCache = function ( + size + ) { + warnInvalidHookAccess(); + return useMemoCache(size); + }; } - if (next === null) { - // This is the new tail of the list - lastScheduledRoot = prev; + { + InvalidNestedHooksDispatcherOnRerenderInDEV.useEffectEvent = + function useEffectEvent(callback) { + currentHookNameInDev = "useEffectEvent"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return updateEvent(callback); + }; } - } else { - // This root still has work. Keep it in the list. - prev = root; - if (includesSyncLane(nextLanes)) { - mightHavePendingSyncWork = true; + if (enableAsyncActions) { + InvalidNestedHooksDispatcherOnRerenderInDEV.useOptimistic = + function useOptimistic(passthrough, reducer) { + currentHookNameInDev = "useOptimistic"; + warnInvalidHookAccess(); + updateHookTypesDev(); + return rerenderOptimistic(passthrough, reducer); + }; } } - root = next; - } - - currentEventTransitionLane = NoLane; // At the end of the microtask, flush any pending synchronous work. This has - // to come at the end, because it does actual rendering work that might throw. - - flushSyncWorkOnAllRoots(); -} - -function scheduleTaskForRootDuringMicrotask(root, currentTime) { - // This function is always called inside a microtask, or at the very end of a - // rendering task right before we yield to the main thread. It should never be - // called synchronously. - // - // TODO: Unless enableDeferRootSchedulingToMicrotask is off. We need to land - // that ASAP to unblock additional features we have planned. - // - // This function also never performs React work synchronously; it should - // only schedule work to be performed later, in a separate task or microtask. - // Check if any lanes are being starved by other work. If so, mark them as - // expired so we know to work on those next. - markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. - - var workInProgressRoot = getWorkInProgressRoot(); - var workInProgressRootRenderLanes = getWorkInProgressRootRenderLanes(); - var nextLanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes - ); - var existingCallbackNode = root.callbackNode; - - if ( - // Check if there's nothing to work on - nextLanes === NoLanes || // If this root is currently suspended and waiting for data to resolve, don't - // schedule a task to render it. We'll either wait for a ping, or wait to - // receive an update. - // - // Suspended render phase - (root === workInProgressRoot && isWorkLoopSuspendedOnData()) || // Suspended commit phase - root.cancelPendingCommit !== null - ) { - // Fast path: There's nothing to work on. - if (existingCallbackNode !== null) { - cancelCallback(existingCallbackNode); - } - - root.callbackNode = null; - root.callbackPriority = NoLane; - return NoLane; - } // Schedule a new callback in the host environment. - - if (includesSyncLane(nextLanes)) { - // Synchronous work is always flushed at the end of the microtask, so we - // don't need to schedule an additional task. - if (existingCallbackNode !== null) { - cancelCallback(existingCallbackNode); - } - - root.callbackPriority = SyncLane; - root.callbackNode = null; - return SyncLane; - } else { - // We use the highest priority lane to represent the priority of the callback. - var existingCallbackPriority = root.callbackPriority; - var newCallbackPriority = getHighestPriorityLane(nextLanes); - - if ( - newCallbackPriority === existingCallbackPriority && // Special case related to `act`. If the currently scheduled task is a - // Scheduler task, rather than an `act` task, cancel it and re-schedule - // on the `act` queue. - !( - ReactCurrentActQueue$2.current !== null && - existingCallbackNode !== fakeActCallbackNode$1 - ) - ) { - // The priority hasn't changed. We can reuse the existing task. - return newCallbackPriority; - } else { - // Cancel the existing callback. We'll schedule a new one below. - cancelCallback(existingCallbackNode); + var now = Scheduler.unstable_now; + var commitTime = 0; + var layoutEffectStartTime = -1; + var profilerStartTime = -1; + var passiveEffectStartTime = -1; + /** + * Tracks whether the current update was a nested/cascading update (scheduled from a layout effect). + * + * The overall sequence is: + * 1. render + * 2. commit (and call `onRender`, `onCommit`) + * 3. check for nested updates + * 4. flush passive effects (and call `onPostCommit`) + * + * Nested updates are identified in step 3 above, + * but step 4 still applies to the work that was just committed. + * We use two flags to track nested updates then: + * one tracks whether the upcoming update is a nested update, + * and the other tracks whether the current update was a nested update. + * The first value gets synced to the second at the start of the render phase. + */ + + var currentUpdateIsNested = false; + var nestedUpdateScheduled = false; + + function isCurrentUpdateNested() { + return currentUpdateIsNested; + } + + function markNestedUpdateScheduled() { + { + nestedUpdateScheduled = true; + } } - var schedulerPriorityLevel; - - switch (lanesToEventPriority(nextLanes)) { - case DiscreteEventPriority: - schedulerPriorityLevel = ImmediatePriority; - break; - - case ContinuousEventPriority: - schedulerPriorityLevel = UserBlockingPriority; - break; - - case DefaultEventPriority: - schedulerPriorityLevel = NormalPriority$1; - break; - - case IdleEventPriority: - schedulerPriorityLevel = IdlePriority; - break; - - default: - schedulerPriorityLevel = NormalPriority$1; - break; + function resetNestedUpdateFlag() { + { + currentUpdateIsNested = false; + nestedUpdateScheduled = false; + } } - var newCallbackNode = scheduleCallback$2( - schedulerPriorityLevel, - performConcurrentWorkOnRoot.bind(null, root) - ); - root.callbackPriority = newCallbackPriority; - root.callbackNode = newCallbackNode; - return newCallbackPriority; - } -} - -function getContinuationForRoot(root, originalCallbackNode) { - // This is called at the end of `performConcurrentWorkOnRoot` to determine - // if we need to schedule a continuation task. - // - // Usually `scheduleTaskForRootDuringMicrotask` only runs inside a microtask; - // however, since most of the logic for determining if we need a continuation - // versus a new task is the same, we cheat a bit and call it here. This is - // only safe to do because we know we're at the end of the browser task. - // So although it's not an actual microtask, it might as well be. - scheduleTaskForRootDuringMicrotask(root, now$1()); - - if (root.callbackNode === originalCallbackNode) { - // The task node scheduled for this root is the same one that's - // currently executed. Need to return a continuation. - return performConcurrentWorkOnRoot.bind(null, root); - } - - return null; -} -var fakeActCallbackNode$1 = {}; - -function scheduleCallback$2(priorityLevel, callback) { - if (ReactCurrentActQueue$2.current !== null) { - // Special case: We're inside an `act` scope (a testing utility). - // Instead of scheduling work in the host environment, add it to a - // fake internal queue that's managed by the `act` implementation. - ReactCurrentActQueue$2.current.push(callback); - return fakeActCallbackNode$1; - } else { - return scheduleCallback$3(priorityLevel, callback); - } -} - -function cancelCallback(callbackNode) { - if (callbackNode === fakeActCallbackNode$1); - else if (callbackNode !== null) { - cancelCallback$1(callbackNode); - } -} - -function scheduleImmediateTask(cb) { - if (ReactCurrentActQueue$2.current !== null) { - // Special case: Inside an `act` scope, we push microtasks to the fake `act` - // callback queue. This is because we currently support calling `act` - // without awaiting the result. The plan is to deprecate that, and require - // that you always await the result so that the microtasks have a chance to - // run. But it hasn't happened yet. - ReactCurrentActQueue$2.current.push(function () { - cb(); - return null; - }); - } // TODO: Can we land supportsMicrotasks? Which environments don't support it? - // Alternatively, can we move this check to the host config? - - { - // If microtasks are not supported, use Scheduler. - scheduleCallback$3(ImmediatePriority, cb); - } -} - -function requestTransitionLane() { - // The algorithm for assigning an update to a lane should be stable for all - // updates at the same priority within the same event. To do this, the - // inputs to the algorithm must be the same. - // - // The trick we use is to cache the first of each of these inputs within an - // event. Then reset the cached values once we can be sure the event is - // over. Our heuristic for that is whenever we enter a concurrent work loop. - if (currentEventTransitionLane === NoLane) { - // All transitions within the same event are assigned the same lane. - currentEventTransitionLane = claimNextTransitionLane(); - } - - return currentEventTransitionLane; -} - -// transition updates that occur while the async action is still in progress -// are treated as part of the action. -// -// The ideal behavior would be to treat each async function as an independent -// action. However, without a mechanism like AsyncContext, we can't tell which -// action an update corresponds to. So instead, we entangle them all into one. -// The listeners to notify once the entangled scope completes. - -var currentEntangledListeners = null; // The number of pending async actions in the entangled scope. - -var currentEntangledPendingCount = 0; // The transition lane shared by all updates in the entangled scope. - -var currentEntangledLane = NoLane; -function requestAsyncActionContext( - actionReturnValue, // If this is provided, this resulting thenable resolves to this value instead - // of the return value of the action. This is a perf trick to avoid composing - // an extra async function. - overrideReturnValue -) { - // This is an async action. - // - // Return a thenable that resolves once the action scope (i.e. the async - // function passed to startTransition) has finished running. - var thenable = actionReturnValue; - var entangledListeners; - - if (currentEntangledListeners === null) { - // There's no outer async action scope. Create a new one. - entangledListeners = currentEntangledListeners = []; - currentEntangledPendingCount = 0; - currentEntangledLane = requestTransitionLane(); - } else { - entangledListeners = currentEntangledListeners; - } - - currentEntangledPendingCount++; // Create a thenable that represents the result of this action, but doesn't - // resolve until the entire entangled scope has finished. - // - // Expressed using promises: - // const [thisResult] = await Promise.all([thisAction, entangledAction]); - // return thisResult; - - var resultThenable = createResultThenable(entangledListeners); - var resultStatus = "pending"; - var resultValue; - var rejectedReason; - thenable.then( - function (value) { - resultStatus = "fulfilled"; - resultValue = overrideReturnValue !== null ? overrideReturnValue : value; - pingEngtangledActionScope(); - }, - function (error) { - resultStatus = "rejected"; - rejectedReason = error; - pingEngtangledActionScope(); - } - ); // Attach a listener to fill in the result. - - entangledListeners.push(function () { - switch (resultStatus) { - case "fulfilled": { - var fulfilledThenable = resultThenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = resultValue; - break; - } - - case "rejected": { - var rejectedThenable = resultThenable; - rejectedThenable.status = "rejected"; - rejectedThenable.reason = rejectedReason; - break; - } - - case "pending": - default: { - // The listener above should have been called first, so `resultStatus` - // should already be set to the correct value. - throw new Error( - "Thenable should have already resolved. This " + "is a bug in React." - ); + function syncNestedUpdateFlag() { + { + currentUpdateIsNested = nestedUpdateScheduled; + nestedUpdateScheduled = false; } } - }); - return resultThenable; -} -function requestSyncActionContext( - actionReturnValue, // If this is provided, this resulting thenable resolves to this value instead - // of the return value of the action. This is a perf trick to avoid composing - // an extra async function. - overrideReturnValue -) { - var resultValue = - overrideReturnValue !== null ? overrideReturnValue : actionReturnValue; // This is not an async action, but it may be part of an outer async action. - - if (currentEntangledListeners === null) { - return resultValue; - } else { - // Return a thenable that does not resolve until the entangled actions - // have finished. - var entangledListeners = currentEntangledListeners; - var resultThenable = createResultThenable(entangledListeners); - entangledListeners.push(function () { - var fulfilledThenable = resultThenable; - fulfilledThenable.status = "fulfilled"; - fulfilledThenable.value = resultValue; - }); - return resultThenable; - } -} - -function pingEngtangledActionScope() { - if ( - currentEntangledListeners !== null && - --currentEntangledPendingCount === 0 - ) { - // All the actions have finished. Close the entangled async action scope - // and notify all the listeners. - var listeners = currentEntangledListeners; - currentEntangledListeners = null; - currentEntangledLane = NoLane; - - for (var i = 0; i < listeners.length; i++) { - var listener = listeners[i]; - listener(); - } - } -} -function createResultThenable(entangledListeners) { - // Waits for the entangled async action to complete, then resolves to the - // result of an individual action. - var resultThenable = { - status: "pending", - value: null, - reason: null, - then: function (resolve) { - // This is a bit of a cheat. `resolve` expects a value of type `S` to be - // passed, but because we're instrumenting the `status` field ourselves, - // and we know this thenable will only be used by React, we also know - // the value isn't actually needed. So we add the resolve function - // directly to the entangled listeners. - // - // This is also why we don't need to check if the thenable is still - // pending; the Suspense implementation already performs that check. - var ping = resolve; - entangledListeners.push(ping); + function getCommitTime() { + return commitTime; } - }; - return resultThenable; -} - -function peekEntangledActionLane() { - return currentEntangledLane; -} -var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, - ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig; -var didWarnAboutMismatchedHooksForComponent; -var didWarnUncachedGetSnapshot; -var didWarnAboutUseWrappedInTryCatch; -var didWarnAboutAsyncClientComponent; - -{ - didWarnAboutMismatchedHooksForComponent = new Set(); - didWarnAboutUseWrappedInTryCatch = new Set(); - didWarnAboutAsyncClientComponent = new Set(); -} // The effect "instance" is a shared object that remains the same for the entire -// lifetime of an effect. In Rust terms, a RefCell. We use it to store the -// "destroy" function that is returned from an effect, because that is stateful. -// The field is `undefined` if the effect is unmounted, or if the effect ran -// but is not stateful. We don't explicitly track whether the effect is mounted -// or unmounted because that can be inferred by the hiddenness of the fiber in -// the tree, i.e. whether there is a hidden Offscreen fiber above it. -// -// It's unfortunate that this is stored on a separate object, because it adds -// more memory per effect instance, but it's conceptually sound. I think there's -// likely a better data structure we could use for effects; perhaps just one -// array of effect instances per fiber. But I think this is OK for now despite -// the additional memory and we can follow up with performance -// optimizations later. -// These are set right before calling the component. - -var renderLanes = NoLanes; // The work-in-progress fiber. I've named it differently to distinguish it from -// the work-in-progress hook. - -var currentlyRenderingFiber$1 = null; // Hooks are stored as a linked list on the fiber's memoizedState field. The -// current hook list is the list that belongs to the current fiber. The -// work-in-progress hook list is a new list that will be added to the -// work-in-progress fiber. - -var currentHook = null; -var workInProgressHook = null; // Whether an update was scheduled at any point during the render phase. This -// does not get reset if we do another render pass; only when we're completely -// finished evaluating this component. This is an optimization so we know -// whether we need to clear render phase updates after a throw. - -var didScheduleRenderPhaseUpdate = false; // Where an update was scheduled only during the current render pass. This -// gets reset after each attempt. -// TODO: Maybe there's some way to consolidate this with -// `didScheduleRenderPhaseUpdate`. Or with `numberOfReRenders`. - -var didScheduleRenderPhaseUpdateDuringThisPass = false; -var shouldDoubleInvokeUserFnsInHooksDEV = false; // Counts the number of useId hooks in this component. - -var thenableIndexCounter = 0; -var thenableState = null; // Used for ids that are generated completely client-side (i.e. not during -// hydration). This counter is global, so client ids are not stable across -// render attempts. - -var globalClientIdCounter = 0; -var RE_RENDER_LIMIT = 25; // In DEV, this is the name of the currently executing primitive hook - -var currentHookNameInDev = null; // In DEV, this list ensures that hooks are called in the same order between renders. -// The list stores the order of hooks used during the initial render (mount). -// Subsequent renders (updates) reference this list. - -var hookTypesDev = null; -var hookTypesUpdateIndexDev = -1; // In DEV, this tracks whether currently rendering component needs to ignore -// the dependencies for Hooks that need them (e.g. useEffect or useMemo). -// When true, such Hooks will always be "remounted". Only used during hot reload. - -var ignorePreviousDependencies = false; - -function mountHookTypesDev() { - { - var hookName = currentHookNameInDev; - - if (hookTypesDev === null) { - hookTypesDev = [hookName]; - } else { - hookTypesDev.push(hookName); + function recordCommitTime() { + commitTime = now(); } - } -} - -function updateHookTypesDev() { - { - var hookName = currentHookNameInDev; - if (hookTypesDev !== null) { - hookTypesUpdateIndexDev++; + function startProfilerTimer(fiber) { + profilerStartTime = now(); - if (hookTypesDev[hookTypesUpdateIndexDev] !== hookName) { - warnOnHookMismatchInDev(hookName); + if (fiber.actualStartTime < 0) { + fiber.actualStartTime = now(); } } - } -} -function checkDepsAreArrayDev(deps) { - { - if (deps !== undefined && deps !== null && !isArray(deps)) { - // Verify deps, but only on mount to avoid extra checks. - // It's unlikely their type would change as usually you define them inline. - 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 - ); + function stopProfilerTimerIfRunning(fiber) { + profilerStartTime = -1; } - } -} - -function warnOnHookMismatchInDev(currentHookName) { - { - var componentName = getComponentNameFromFiber(currentlyRenderingFiber$1); - if (!didWarnAboutMismatchedHooksForComponent.has(componentName)) { - didWarnAboutMismatchedHooksForComponent.add(componentName); - - if (hookTypesDev !== null) { - var table = ""; - var secondColumnStart = 30; - - for (var i = 0; i <= hookTypesUpdateIndexDev; i++) { - var oldHookName = hookTypesDev[i]; - var newHookName = - i === hookTypesUpdateIndexDev ? currentHookName : oldHookName; - var row = i + 1 + ". " + oldHookName; // Extra space so second column lines up - // lol @ IE not supporting String#repeat - - while (row.length < secondColumnStart) { - row += " "; - } + function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { + if (profilerStartTime >= 0) { + var elapsedTime = now() - profilerStartTime; + fiber.actualDuration += elapsedTime; - row += newHookName + "\n"; - table += row; + if (overrideBaseTime) { + fiber.selfBaseDuration = elapsedTime; } - 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 - ); + profilerStartTime = -1; } } - } -} -function warnIfAsyncClientComponent(Component, componentDoesIncludeHooks) { - { - // This dev-only check only works for detecting native async functions, - // not transpiled ones. There's also a prod check that we use to prevent - // async client components from crashing the app; the prod one works even - // for transpiled async functions. Neither mechanism is completely - // bulletproof but together they cover the most common cases. - var isAsyncFunction = // $FlowIgnore[method-unbinding] - Object.prototype.toString.call(Component) === "[object AsyncFunction]"; - - if (isAsyncFunction) { - // Encountered an async Client Component. This is not yet supported, - // except in certain constrained cases, like during a route navigation. - var componentName = getComponentNameFromFiber(currentlyRenderingFiber$1); - - if (!didWarnAboutAsyncClientComponent.has(componentName)) { - didWarnAboutAsyncClientComponent.add(componentName); // Check if this is a sync update. We use the "root" render lanes here - // because the "subtree" render lanes may include additional entangled - // lanes related to revealing previously hidden content. + function recordLayoutEffectDuration(fiber) { + if (layoutEffectStartTime >= 0) { + var elapsedTime = now() - layoutEffectStartTime; + layoutEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor + // Or the root (for the DevTools Profiler to read) - var root = getWorkInProgressRoot(); - var rootRenderLanes = getWorkInProgressRootRenderLanes(); + var parentFiber = fiber.return; - if (root !== null && includesBlockingLane(root, rootRenderLanes)) { - error( - "async/await is not yet supported in Client Components, only " + - "Server Components. This error is often caused by accidentally " + - "adding `'use client'` to a module that was originally written " + - "for the server." - ); - } else { - // This is a concurrent (Transition, Retry, etc) render. We don't - // warn in these cases. - // - // However, Async Components are forbidden to include hooks, even - // during a transition, so let's check for that here. - // - // TODO: Add a corresponding warning to Server Components runtime. - if (componentDoesIncludeHooks) { - error( - "Hooks are not supported inside an async component. This " + - "error is often caused by accidentally adding `'use client'` " + - "to a module that was originally written for the server." - ); + while (parentFiber !== null) { + switch (parentFiber.tag) { + case HostRoot: + var root = parentFiber.stateNode; + root.effectDuration += elapsedTime; + return; + + case Profiler: + var parentStateNode = parentFiber.stateNode; + parentStateNode.effectDuration += elapsedTime; + return; } + + parentFiber = parentFiber.return; } } } - } -} - -function throwInvalidHookError() { - 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." - ); -} -function areHookInputsEqual(nextDeps, prevDeps) { - { - if (ignorePreviousDependencies) { - // Only true when this component is being hot reloaded. - return false; - } - } + function recordPassiveEffectDuration(fiber) { + if (passiveEffectStartTime >= 0) { + var elapsedTime = now() - passiveEffectStartTime; + passiveEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor + // Or the root (for the DevTools Profiler to read) - if (prevDeps === null) { - { - 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 - ); - } + var parentFiber = fiber.return; - return false; - } - - { - // Don't bother comparing lengths in prod because these arrays should be - // passed inline. - if (nextDeps.length !== prevDeps.length) { - 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(", ") + "]" - ); - } - } // $FlowFixMe[incompatible-use] found when upgrading Flow + while (parentFiber !== null) { + switch (parentFiber.tag) { + case HostRoot: + var root = parentFiber.stateNode; - for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - if (objectIs(nextDeps[i], prevDeps[i])) { - continue; - } + if (root !== null) { + root.passiveEffectDuration += elapsedTime; + } - return false; - } + return; - return true; -} + case Profiler: + var parentStateNode = parentFiber.stateNode; -function renderWithHooks( - current, - workInProgress, - Component, - props, - secondArg, - nextRenderLanes -) { - renderLanes = nextRenderLanes; - currentlyRenderingFiber$1 = workInProgress; - - { - hookTypesDev = current !== null ? current._debugHookTypes : null; - hookTypesUpdateIndexDev = -1; // Used for hot reloading: - - ignorePreviousDependencies = - current !== null && current.type !== workInProgress.type; - } - - workInProgress.memoizedState = null; - workInProgress.updateQueue = null; - workInProgress.lanes = NoLanes; // The following should have already been reset - // currentHook = null; - // workInProgressHook = null; - // didScheduleRenderPhaseUpdate = false; - // localIdCounter = 0; - // thenableIndexCounter = 0; - // thenableState = null; - // TODO Warn if no hooks are used at all during mount, then some are used during update. - // Currently we will identify the update render as a mount because memoizedState === null. - // This is tricky because it's valid for certain types of components (e.g. React.lazy) - // Using memoizedState to differentiate between mount/update only works if at least one stateful hook is used. - // Non-stateful hooks (e.g. context) don't get added to memoizedState, - // so memoizedState would be null during updates and mounts. - - { - if (current !== null && current.memoizedState !== null) { - ReactCurrentDispatcher$1.current = HooksDispatcherOnUpdateInDEV; - } else if (hookTypesDev !== null) { - // This dispatcher handles an edge case where a component is updating, - // but no stateful hooks have been used. - // We want to match the production code behavior (which will use HooksDispatcherOnMount), - // but with the extra DEV validation to ensure hooks ordering hasn't changed. - // This dispatcher does that. - ReactCurrentDispatcher$1.current = - HooksDispatcherOnMountWithHookTypesInDEV; - } else { - ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; - } - } // In Strict Mode, during development, user functions are double invoked to - // help detect side effects. The logic for how this is implemented for in - // hook components is a bit complex so let's break it down. - // - // We will invoke the entire component function twice. However, during the - // second invocation of the component, the hook state from the first - // invocation will be reused. That means things like `useMemo` functions won't - // run again, because the deps will match and the memoized result will - // be reused. - // - // We want memoized functions to run twice, too, so account for this, user - // functions are double invoked during the *first* invocation of the component - // function, and are *not* double invoked during the second incovation: - // - // - First execution of component function: user functions are double invoked - // - Second execution of component function (in Strict Mode, during - // development): user functions are not double invoked. - // - // This is intentional for a few reasons; most importantly, it's because of - // how `use` works when something suspends: it reuses the promise that was - // passed during the first attempt. This is itself a form of memoization. - // We need to be able to memoize the reactive inputs to the `use` call using - // a hook (i.e. `useMemo`), which means, the reactive inputs to `use` must - // come from the same component invocation as the output. - // - // There are plenty of tests to ensure this behavior is correct. - - var shouldDoubleRenderDEV = - (workInProgress.mode & StrictLegacyMode) !== NoMode; - shouldDoubleInvokeUserFnsInHooksDEV = shouldDoubleRenderDEV; - var children = Component(props, secondArg); - shouldDoubleInvokeUserFnsInHooksDEV = false; // Check if there was a render phase update - - if (didScheduleRenderPhaseUpdateDuringThisPass) { - // Keep rendering until the component stabilizes (there are no more render - // phase updates). - children = renderWithHooksAgain( - workInProgress, - Component, - props, - secondArg - ); - } + if (parentStateNode !== null) { + // Detached fibers have their state node cleared out. + // In this case, the return pointer is also cleared out, + // so we won't be able to report the time spent in this Profiler's subtree. + parentStateNode.passiveEffectDuration += elapsedTime; + } - if (shouldDoubleRenderDEV) { - // In development, components are invoked twice to help detect side effects. - setIsStrictModeForDevtools(true); + return; + } - try { - children = renderWithHooksAgain( - workInProgress, - Component, - props, - secondArg - ); - } finally { - setIsStrictModeForDevtools(false); + parentFiber = parentFiber.return; + } + } } - } - - finishRenderingHooks(current, workInProgress, Component); - return children; -} -function finishRenderingHooks(current, workInProgress, Component) { - { - workInProgress._debugHookTypes = hookTypesDev; - var componentDoesIncludeHooks = - workInProgressHook !== null || thenableIndexCounter !== 0; - warnIfAsyncClientComponent(Component, componentDoesIncludeHooks); - } // We can assume the previous dispatcher is always this one, since we set it - // at the beginning of the render phase and there's no re-entrance. - - ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; // This check uses currentHook so that it works the same in DEV and prod bundles. - // hookTypesDev could catch more cases (e.g. context) but only in DEV bundles. - - var didRenderTooFewHooks = currentHook !== null && currentHook.next !== null; - renderLanes = NoLanes; - currentlyRenderingFiber$1 = null; - currentHook = null; - workInProgressHook = null; - - { - currentHookNameInDev = null; - hookTypesDev = null; - hookTypesUpdateIndexDev = -1; // Confirm that a static flag was not added or removed since the last - // render. If this fires, it suggests that we incorrectly reset the static - // flags in some other part of the codebase. This has happened before, for - // example, in the SuspenseList implementation. - - if ( - current !== null && - (current.flags & StaticMask) !== (workInProgress.flags & StaticMask) && // Disable this warning in legacy mode, because legacy Suspense is weird - // and creates false positives. To make this work in legacy mode, we'd - // need to mark fibers that commit in an incomplete state, somehow. For - // now I'll disable the warning that most of the bugs that would trigger - // it are either exclusive to concurrent mode or exist in both. - (current.mode & ConcurrentMode) !== NoMode - ) { - error( - "Internal React error: Expected static flag was missing. Please " + - "notify the React team." - ); + function startLayoutEffectTimer() { + layoutEffectStartTime = now(); } - } - didScheduleRenderPhaseUpdate = false; // This is reset by checkDidRenderIdHook - // localIdCounter = 0; - - thenableIndexCounter = 0; - thenableState = null; - - if (didRenderTooFewHooks) { - throw new Error( - "Rendered fewer hooks than expected. This may be caused by an accidental " + - "early return statement." - ); - } - - if (enableLazyContextPropagation) { - if (current !== null) { - if (!checkIfWorkInProgressReceivedUpdate()) { - // If there were no changes to props or state, we need to check if there - // was a context change. We didn't already do this because there's no - // 1:1 correspondence between dependencies and hooks. Although, because - // there almost always is in the common case (`readContext` is an - // internal API), we could compare in there. OTOH, we only hit this case - // if everything else bails out, so on the whole it might be better to - // keep the comparison out of the common path. - var currentDependencies = current.dependencies; - - if ( - currentDependencies !== null && - checkIfContextChanged(currentDependencies) - ) { - markWorkInProgressReceivedUpdate(); - } - } + function startPassiveEffectTimer() { + passiveEffectStartTime = now(); } - } - { - if (checkIfUseWrappedInTryCatch()) { - var componentName = - getComponentNameFromFiber(workInProgress) || "Unknown"; - - if ( - !didWarnAboutUseWrappedInTryCatch.has(componentName) && // This warning also fires if you suspend with `use` inside an - // async component. Since we warn for that above, we'll silence this - // second warning by checking here. - !didWarnAboutAsyncClientComponent.has(componentName) - ) { - didWarnAboutUseWrappedInTryCatch.add(componentName); + function transferActualDuration(fiber) { + // Transfer time spent rendering these children so we don't lose it + // after we rerender. This is used as a helper in special cases + // where we should count the work of multiple passes. + var child = fiber.child; - error( - "`use` was called from inside a try/catch block. This is not allowed " + - "and can lead to unexpected behavior. To handle errors triggered " + - "by `use`, wrap your component in a error boundary." - ); + while (child) { + // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + fiber.actualDuration += child.actualDuration; + child = child.sibling; } } - } -} -function replaySuspendedComponentWithHooks( - current, - workInProgress, - Component, - props, - secondArg -) { - // This function is used to replay a component that previously suspended, - // after its data resolves. - // - // It's a simplified version of renderWithHooks, but it doesn't need to do - // most of the set up work because they weren't reset when we suspended; they - // only get reset when the component either completes (finishRenderingHooks) - // or unwinds (resetHooksOnUnwind). - { - hookTypesUpdateIndexDev = -1; // Used for hot reloading: - - ignorePreviousDependencies = - current !== null && current.type !== workInProgress.type; - } - - var children = renderWithHooksAgain( - workInProgress, - Component, - props, - secondArg - ); - finishRenderingHooks(current, workInProgress, Component); - return children; -} + function resolveDefaultProps(Component, baseProps) { + if (Component && Component.defaultProps) { + // Resolve default props. Taken from ReactElement + var props = assign({}, baseProps); + var defaultProps = Component.defaultProps; -function renderWithHooksAgain(workInProgress, Component, props, secondArg) { - // This is used to perform another render pass. It's used when setState is - // called during render, and for double invoking components in Strict Mode - // during development. - // - // The state from the previous pass is reused whenever possible. So, state - // updates that were already processed are not processed again, and memoized - // functions (`useMemo`) are not invoked again. - // - // Keep rendering in a loop for as long as render phase updates continue to - // be scheduled. Use a counter to prevent infinite loops. - currentlyRenderingFiber$1 = workInProgress; - var numberOfReRenders = 0; - var children; - - do { - if (didScheduleRenderPhaseUpdateDuringThisPass) { - // It's possible that a use() value depended on a state that was updated in - // this rerender, so we need to watch for different thenables this time. - thenableState = null; - } + for (var propName in defaultProps) { + if (props[propName] === undefined) { + props[propName] = defaultProps[propName]; + } + } - thenableIndexCounter = 0; - didScheduleRenderPhaseUpdateDuringThisPass = false; + return props; + } - if (numberOfReRenders >= RE_RENDER_LIMIT) { - throw new Error( - "Too many re-renders. React limits the number of renders to prevent " + - "an infinite loop." - ); + return baseProps; } - numberOfReRenders += 1; - - { - // Even when hot reloading, allow dependencies to stabilize - // after first render to prevent infinite render phase updates. - ignorePreviousDependencies = false; - } // Start over from the beginning of the list - - currentHook = null; - workInProgressHook = null; - workInProgress.updateQueue = null; + var fakeInternalInstance = {}; + var didWarnAboutStateAssignmentForComponent; + var didWarnAboutUninitializedState; + var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate; + var didWarnAboutLegacyLifecyclesAndDerivedState; + var didWarnAboutUndefinedDerivedState; + var didWarnAboutDirectlyAssigningPropsToState; + var didWarnAboutInvalidateContextType; + var didWarnOnInvalidCallback; { - // Also validate hook order for cascading updates. - hookTypesUpdateIndexDev = -1; + didWarnAboutStateAssignmentForComponent = new Set(); + didWarnAboutUninitializedState = new Set(); + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set(); + didWarnAboutLegacyLifecyclesAndDerivedState = new Set(); + didWarnAboutDirectlyAssigningPropsToState = new Set(); + didWarnAboutUndefinedDerivedState = new Set(); + didWarnAboutInvalidateContextType = new Set(); + didWarnOnInvalidCallback = new Set(); // This is so gross but it's at least non-critical and can be removed if + // it causes problems. This is meant to give a nicer error message for + // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component, + // ...)) which otherwise throws a "_processChildContext is not a function" + // exception. + + Object.defineProperty(fakeInternalInstance, "_processChildContext", { + enumerable: false, + value: function () { + 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)." + ); + } + }); + Object.freeze(fakeInternalInstance); } - ReactCurrentDispatcher$1.current = HooksDispatcherOnRerenderInDEV; - children = Component(props, secondArg); - } while (didScheduleRenderPhaseUpdateDuringThisPass); - - return children; -} -function bailoutHooks(current, workInProgress, lanes) { - workInProgress.updateQueue = current.updateQueue; // TODO: Don't need to reset the flags here, because they're reset in the - // complete phase (bubbleProperties). - - if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { - workInProgress.flags &= ~( - MountPassiveDev | - MountLayoutDev | - Passive$1 | - Update - ); - } else { - workInProgress.flags &= ~(Passive$1 | Update); - } + function warnOnInvalidCallback(callback, callerName) { + { + if (callback === null || typeof callback === "function") { + return; + } - current.lanes = removeLanes(current.lanes, lanes); -} -function resetHooksAfterThrow() { - // This is called immediaetly after a throw. It shouldn't reset the entire - // module state, because the work loop might decide to replay the component - // again without rewinding. - // - // It should only reset things like the current dispatcher, to prevent hooks - // from being called outside of a component. - currentlyRenderingFiber$1 = null; // We can assume the previous dispatcher is always this one, since we set it - // at the beginning of the render phase and there's no re-entrance. - - ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; -} -function resetHooksOnUnwind(workInProgress) { - if (didScheduleRenderPhaseUpdate) { - // There were render phase updates. These are only valid for this render - // phase, which we are now aborting. Remove the updates from the queues so - // they do not persist to the next render. Do not remove updates from hooks - // that weren't processed. - // - // Only reset the updates from the queue if it has a clone. If it does - // not have a clone, that means it wasn't processed, and the updates were - // scheduled before we entered the render phase. - var hook = workInProgress.memoizedState; + var key = callerName + "_" + callback; - while (hook !== null) { - var queue = hook.queue; + if (!didWarnOnInvalidCallback.has(key)) { + didWarnOnInvalidCallback.add(key); - if (queue !== null) { - queue.pending = null; + error( + "%s(...): Expected the last optional `callback` argument to be a " + + "function. Instead received: %s.", + callerName, + callback + ); + } } - - hook = hook.next; } - didScheduleRenderPhaseUpdate = false; - } - - renderLanes = NoLanes; - currentlyRenderingFiber$1 = null; - currentHook = null; - workInProgressHook = null; - - { - hookTypesDev = null; - hookTypesUpdateIndexDev = -1; - currentHookNameInDev = null; - } - - didScheduleRenderPhaseUpdateDuringThisPass = false; - thenableIndexCounter = 0; - thenableState = null; -} - -function mountWorkInProgressHook() { - var hook = { - memoizedState: null, - baseState: null, - baseQueue: null, - queue: null, - next: null - }; - - if (workInProgressHook === null) { - // This is the first hook in the list - currentlyRenderingFiber$1.memoizedState = workInProgressHook = hook; - } else { - // Append to the end of the list - workInProgressHook = workInProgressHook.next = hook; - } - - return workInProgressHook; -} - -function updateWorkInProgressHook() { - // This function is used both for updates and for re-renders triggered by a - // render phase update. It assumes there is either a current hook we can - // clone, or a work-in-progress hook from a previous render pass that we can - // use as a base. - var nextCurrentHook; - - if (currentHook === null) { - var current = currentlyRenderingFiber$1.alternate; + function warnOnUndefinedDerivedState(type, partialState) { + { + if (partialState === undefined) { + var componentName = getComponentNameFromType(type) || "Component"; - if (current !== null) { - nextCurrentHook = current.memoizedState; - } else { - nextCurrentHook = null; - } - } else { - nextCurrentHook = currentHook.next; - } - - var nextWorkInProgressHook; - - if (workInProgressHook === null) { - nextWorkInProgressHook = currentlyRenderingFiber$1.memoizedState; - } else { - nextWorkInProgressHook = workInProgressHook.next; - } - - if (nextWorkInProgressHook !== null) { - // There's already a work-in-progress. Reuse it. - workInProgressHook = nextWorkInProgressHook; - nextWorkInProgressHook = workInProgressHook.next; - currentHook = nextCurrentHook; - } else { - // Clone from the current hook. - if (nextCurrentHook === null) { - var currentFiber = currentlyRenderingFiber$1.alternate; + if (!didWarnAboutUndefinedDerivedState.has(componentName)) { + didWarnAboutUndefinedDerivedState.add(componentName); - if (currentFiber === null) { - // This is the initial render. This branch is reached when the component - // suspends, resumes, then renders an additional hook. - // Should never be reached because we should switch to the mount dispatcher first. - throw new Error( - "Update hook called on initial render. This is likely a bug in React. Please file an issue." - ); - } else { - // This is an update. We should always have a current hook. - throw new Error("Rendered more hooks than during the previous render."); + error( + "%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. " + + "You have returned undefined.", + componentName + ); + } + } } } - currentHook = nextCurrentHook; - var newHook = { - memoizedState: currentHook.memoizedState, - baseState: currentHook.baseState, - baseQueue: currentHook.baseQueue, - queue: currentHook.queue, - next: null - }; - - if (workInProgressHook === null) { - // This is the first hook in the list. - currentlyRenderingFiber$1.memoizedState = workInProgressHook = newHook; - } else { - // Append to the end of the list. - workInProgressHook = workInProgressHook.next = newHook; - } - } - - return workInProgressHook; -} // NOTE: defining two versions of this function to avoid size impact when this feature is disabled. -// Previously this function was inlined, the additional `memoCache` property makes it not inlined. + function applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + nextProps + ) { + var prevState = workInProgress.memoizedState; + var partialState = getDerivedStateFromProps(nextProps, prevState); -var createFunctionComponentUpdateQueue; + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); -{ - createFunctionComponentUpdateQueue = function () { - return { - lastEffect: null, - events: null, - stores: null, - memoCache: null - }; - }; -} + try { + // Invoke the function an extra time to help detect side-effects. + partialState = getDerivedStateFromProps(nextProps, prevState); + } finally { + setIsStrictModeForDevtools(false); + } + } -function useThenable(thenable) { - // Track the position of the thenable within this fiber. - var index = thenableIndexCounter; - thenableIndexCounter += 1; - - if (thenableState === null) { - thenableState = createThenableState(); - } - - var result = trackUsedThenable(thenableState, thenable, index); - - if ( - currentlyRenderingFiber$1.alternate === null && - (workInProgressHook === null - ? currentlyRenderingFiber$1.memoizedState === null - : workInProgressHook.next === null) - ) { - // Initial render, and either this is the first time the component is - // called, or there were no Hooks called after this use() the previous - // time (perhaps because it threw). Subsequent Hook calls should use the - // mount dispatcher. - { - ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; - } - } + warnOnUndefinedDerivedState(ctor, partialState); + } // Merge the partial state and the previous state. - return result; -} + var memoizedState = + partialState === null || partialState === undefined + ? prevState + : assign({}, prevState, partialState); + workInProgress.memoizedState = memoizedState; // Once the update queue is empty, persist the derived state onto the + // base state. -function use(usable) { - if (usable !== null && typeof usable === "object") { - // $FlowFixMe[method-unbinding] - if (typeof usable.then === "function") { - // This is a thenable. - var thenable = usable; - return useThenable(thenable); - } else if ( - usable.$$typeof === REACT_CONTEXT_TYPE || - usable.$$typeof === REACT_SERVER_CONTEXT_TYPE - ) { - var context = usable; - return readContext(context); + if (workInProgress.lanes === NoLanes) { + // Queue is always non-null for classes + var updateQueue = workInProgress.updateQueue; + updateQueue.baseState = memoizedState; + } } - } // eslint-disable-next-line react-internal/safe-string-coercion - throw new Error("An unsupported type was passed to use(): " + String(usable)); -} + var classComponentUpdater = { + isMounted: isMounted, + // $FlowFixMe[missing-local-annot] + enqueueSetState: function (inst, payload, callback) { + var fiber = get(inst); + var lane = requestUpdateLane(fiber); + var update = createUpdate(lane); + update.payload = payload; -function useMemoCache(size) { - var memoCache = null; // Fast-path, load memo cache from wip fiber if already prepared + if (callback !== undefined && callback !== null) { + { + warnOnInvalidCallback(callback, "setState"); + } - var updateQueue = currentlyRenderingFiber$1.updateQueue; + update.callback = callback; + } - if (updateQueue !== null) { - memoCache = updateQueue.memoCache; - } // Otherwise clone from the current fiber + var root = enqueueUpdate(fiber, update, lane); - if (memoCache == null) { - var current = currentlyRenderingFiber$1.alternate; + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane); + entangleTransitions(root, fiber, lane); + } - if (current !== null) { - var currentUpdateQueue = current.updateQueue; + { + if (enableDebugTracing) { + if (fiber.mode & DebugTracingMode) { + var name = getComponentNameFromFiber(fiber) || "Unknown"; + logStateUpdateScheduled(name, lane, payload); + } + } + } - if (currentUpdateQueue !== null) { - var currentMemoCache = currentUpdateQueue.memoCache; + if (enableSchedulingProfiler) { + markStateUpdateScheduled(fiber, lane); + } + }, + enqueueReplaceState: function (inst, payload, callback) { + var fiber = get(inst); + var lane = requestUpdateLane(fiber); + var update = createUpdate(lane); + update.tag = ReplaceState; + update.payload = payload; + + if (callback !== undefined && callback !== null) { + { + warnOnInvalidCallback(callback, "replaceState"); + } - if (currentMemoCache != null) { - memoCache = { - data: currentMemoCache.data.map(function (array) { - return array.slice(); - }), - index: 0 - }; + update.callback = callback; } - } - } - } // Finally fall back to allocating a fresh instance of the cache - if (memoCache == null) { - memoCache = { - data: [], - index: 0 - }; - } + var root = enqueueUpdate(fiber, update, lane); - if (updateQueue === null) { - updateQueue = createFunctionComponentUpdateQueue(); - currentlyRenderingFiber$1.updateQueue = updateQueue; - } + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane); + entangleTransitions(root, fiber, lane); + } - updateQueue.memoCache = memoCache; - var data = memoCache.data[memoCache.index]; + { + if (enableDebugTracing) { + if (fiber.mode & DebugTracingMode) { + var name = getComponentNameFromFiber(fiber) || "Unknown"; + logStateUpdateScheduled(name, lane, payload); + } + } + } - if (data === undefined) { - data = memoCache.data[memoCache.index] = new Array(size); + if (enableSchedulingProfiler) { + markStateUpdateScheduled(fiber, lane); + } + }, + // $FlowFixMe[missing-local-annot] + enqueueForceUpdate: function (inst, callback) { + var fiber = get(inst); + var lane = requestUpdateLane(fiber); + var update = createUpdate(lane); + update.tag = ForceUpdate; + + if (callback !== undefined && callback !== null) { + { + warnOnInvalidCallback(callback, "forceUpdate"); + } - for (var i = 0; i < size; i++) { - data[i] = REACT_MEMO_CACHE_SENTINEL; - } - } else if (data.length !== size) { - // TODO: consider warning or throwing here - { - error( - "Expected a constant size argument for each invocation of useMemoCache. " + - "The previous cache was allocated with size %s but size %s was requested.", - data.length, - size - ); - } - } + update.callback = callback; + } - memoCache.index++; - return data; -} + var root = enqueueUpdate(fiber, update, lane); -function basicStateReducer(state, action) { - // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types - return typeof action === "function" ? action(state) : action; -} + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, lane); + entangleTransitions(root, fiber, lane); + } -function mountReducer(reducer, initialArg, init) { - var hook = mountWorkInProgressHook(); - var initialState; - - if (init !== undefined) { - initialState = init(initialArg); - } else { - initialState = initialArg; - } - - hook.memoizedState = hook.baseState = initialState; - var queue = { - pending: null, - lanes: NoLanes, - dispatch: null, - lastRenderedReducer: reducer, - lastRenderedState: initialState - }; - hook.queue = queue; - var dispatch = (queue.dispatch = dispatchReducerAction.bind( - null, - currentlyRenderingFiber$1, - queue - )); - return [hook.memoizedState, dispatch]; -} + { + if (enableDebugTracing) { + if (fiber.mode & DebugTracingMode) { + var name = getComponentNameFromFiber(fiber) || "Unknown"; + logForceUpdateScheduled(name, lane); + } + } + } -function updateReducer(reducer, initialArg, init) { - var hook = updateWorkInProgressHook(); - return updateReducerImpl(hook, currentHook, reducer); -} + if (enableSchedulingProfiler) { + markForceUpdateScheduled(fiber, lane); + } + } + }; -function updateReducerImpl(hook, current, reducer) { - var queue = hook.queue; + function checkShouldComponentUpdate( + workInProgress, + ctor, + oldProps, + newProps, + oldState, + newState, + nextContext + ) { + var instance = workInProgress.stateNode; - if (queue === null) { - throw new Error( - "Should have a queue. This is likely a bug in React. Please file an issue." - ); - } + if (typeof instance.shouldComponentUpdate === "function") { + var shouldUpdate = instance.shouldComponentUpdate( + newProps, + newState, + nextContext + ); - queue.lastRenderedReducer = reducer; // The last rebase update that is NOT part of the base state. + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); - var baseQueue = hook.baseQueue; // The last pending update that hasn't been processed yet. + try { + // Invoke the function an extra time to help detect side-effects. + shouldUpdate = instance.shouldComponentUpdate( + newProps, + newState, + nextContext + ); + } finally { + setIsStrictModeForDevtools(false); + } + } - var pendingQueue = queue.pending; + if (shouldUpdate === undefined) { + error( + "%s.shouldComponentUpdate(): Returned undefined instead of a " + + "boolean value. Make sure to return true or false.", + getComponentNameFromType(ctor) || "Component" + ); + } + } - if (pendingQueue !== null) { - // We have new updates that haven't been processed yet. - // We'll add them to the base queue. - if (baseQueue !== null) { - // Merge the pending queue and the base queue. - var baseFirst = baseQueue.next; - var pendingFirst = pendingQueue.next; - baseQueue.next = pendingFirst; - pendingQueue.next = baseFirst; - } + return shouldUpdate; + } - { - if (current.baseQueue !== baseQueue) { - // Internal invariant that should never happen, but feasibly could in - // the future if we implement resuming, or some form of that. - error( - "Internal error: Expected work-in-progress queue to be a clone. " + - "This is a bug in React." + if (ctor.prototype && ctor.prototype.isPureReactComponent) { + return ( + !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) ); } + + return true; } - current.baseQueue = baseQueue = pendingQueue; - queue.pending = null; - } - - if (baseQueue !== null) { - // We have a queue to process. - var first = baseQueue.next; - var newState = hook.baseState; - var newBaseState = null; - var newBaseQueueFirst = null; - var newBaseQueueLast = null; - var update = first; - - do { - // An extra OffscreenLane bit is added to updates that were made to - // a hidden tree, so that we can distinguish them from updates that were - // already there when the tree was hidden. - var updateLane = removeLanes(update.lane, OffscreenLane); - var isHiddenUpdate = updateLane !== update.lane; // Check if this update was made while the tree was hidden. If so, then - // it's not a "base" update and we should disregard the extra base lanes - // that were added to renderLanes when we entered the Offscreen tree. - - var shouldSkipUpdate = isHiddenUpdate - ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) - : !isSubsetOfLanes(renderLanes, updateLane); - - if (shouldSkipUpdate) { - // Priority is insufficient. Skip this update. If this is the first - // skipped update, the previous update/state is the new base - // update/state. - var clone = { - lane: updateLane, - revertLane: update.revertLane, - action: update.action, - hasEagerState: update.hasEagerState, - eagerState: update.eagerState, - next: null - }; + function checkClassInstance(workInProgress, ctor, newProps) { + var instance = workInProgress.stateNode; - if (newBaseQueueLast === null) { - newBaseQueueFirst = newBaseQueueLast = clone; - newBaseState = newState; - } else { - newBaseQueueLast = newBaseQueueLast.next = clone; - } // Update the remaining priority in the queue. - // TODO: Don't need to accumulate this. Instead, we can remove - // renderLanes from the original lanes. + { + var name = getComponentNameFromType(ctor) || "Component"; + var renderPresent = instance.render; - currentlyRenderingFiber$1.lanes = mergeLanes( - currentlyRenderingFiber$1.lanes, - updateLane - ); - markSkippedUpdateLanes(updateLane); - } else { - // This update does have sufficient priority. - // Check if this is an optimistic update. - var revertLane = update.revertLane; - - if (!enableAsyncActions || revertLane === NoLane) { - // This is not an optimistic update, and we're going to apply it now. - // But, if there were earlier updates that were skipped, we need to - // leave this update in the queue so it can be rebased later. - if (newBaseQueueLast !== null) { - var _clone = { - // This update is going to be committed so we never want uncommit - // it. Using NoLane works because 0 is a subset of all bitmasks, so - // this will never be skipped by the check above. - lane: NoLane, - revertLane: NoLane, - action: update.action, - hasEagerState: update.hasEagerState, - eagerState: update.eagerState, - next: null - }; - newBaseQueueLast = newBaseQueueLast.next = _clone; - } - } else { - // This is an optimistic update. If the "revert" priority is - // sufficient, don't apply the update. Otherwise, apply the update, - // but leave it in the queue so it can be either reverted or - // rebased in a subsequent render. - if (isSubsetOfLanes(renderLanes, revertLane)) { - // The transition that this optimistic update is associated with - // has finished. Pretend the update doesn't exist by skipping - // over it. - update = update.next; - continue; + if (!renderPresent) { + if (ctor.prototype && typeof ctor.prototype.render === "function") { + error( + "%s(...): No `render` method found on the returned component " + + "instance: did you accidentally return an object from the constructor?", + name + ); } else { - var _clone2 = { - // Once we commit an optimistic update, we shouldn't uncommit it - // until the transition it is associated with has finished - // (represented by revertLane). Using NoLane here works because 0 - // is a subset of all bitmasks, so this will never be skipped by - // the check above. - lane: NoLane, - // Reuse the same revertLane so we know when the transition - // has finished. - revertLane: update.revertLane, - action: update.action, - hasEagerState: update.hasEagerState, - eagerState: update.eagerState, - next: null - }; - - if (newBaseQueueLast === null) { - newBaseQueueFirst = newBaseQueueLast = _clone2; - newBaseState = newState; - } else { - newBaseQueueLast = newBaseQueueLast.next = _clone2; - } // Update the remaining priority in the queue. - // TODO: Don't need to accumulate this. Instead, we can remove - // renderLanes from the original lanes. - - currentlyRenderingFiber$1.lanes = mergeLanes( - currentlyRenderingFiber$1.lanes, - revertLane + error( + "%s(...): No `render` method found on the returned component " + + "instance: you may have forgotten to define `render`.", + name ); - markSkippedUpdateLanes(revertLane); } - } // Process this update. - - var action = update.action; + } - if (shouldDoubleInvokeUserFnsInHooksDEV) { - reducer(newState, action); + if ( + instance.getInitialState && + !instance.getInitialState.isReactClassApproved && + !instance.state + ) { + 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 + ); } - if (update.hasEagerState) { - // If this update is a state update (not a reducer) and was processed eagerly, - // we can use the eagerly computed state - newState = update.eagerState; - } else { - newState = reducer(newState, action); + if ( + instance.getDefaultProps && + !instance.getDefaultProps.isReactClassApproved + ) { + 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 + ); } - } - update = update.next; - } while (update !== null && update !== first); + if (instance.propTypes) { + error( + "propTypes was defined as an instance property on %s. Use a static " + + "property to define propTypes instead.", + name + ); + } - if (newBaseQueueLast === null) { - newBaseState = newState; - } else { - newBaseQueueLast.next = newBaseQueueFirst; - } // Mark that the fiber performed work, but only if the new state is - // different from the current state. + if (instance.contextType) { + error( + "contextType was defined as an instance property on %s. Use a static " + + "property to define contextType instead.", + name + ); + } - if (!objectIs(newState, hook.memoizedState)) { - markWorkInProgressReceivedUpdate(); - } + { + if (ctor.childContextTypes) { + error( + "%s uses the legacy childContextTypes API which is no longer supported. " + + "Use React.createContext() instead.", + name + ); + } - hook.memoizedState = newState; - hook.baseState = newBaseState; - hook.baseQueue = newBaseQueueLast; - queue.lastRenderedState = newState; - } + if (ctor.contextTypes) { + error( + "%s uses the legacy contextTypes API which is no longer supported. " + + "Use React.createContext() with static contextType instead.", + name + ); + } + } - if (baseQueue === null) { - // `queue.lanes` is used for entangling transitions. We can set it back to - // zero once the queue is empty. - queue.lanes = NoLanes; - } + if (typeof instance.componentShouldUpdate === "function") { + 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 + ); + } - var dispatch = queue.dispatch; - return [hook.memoizedState, dispatch]; -} + if ( + ctor.prototype && + ctor.prototype.isPureReactComponent && + typeof instance.shouldComponentUpdate !== "undefined" + ) { + 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" + ); + } -function rerenderReducer(reducer, initialArg, init) { - var hook = updateWorkInProgressHook(); - var queue = hook.queue; + if (typeof instance.componentDidUnmount === "function") { + error( + "%s has a method called " + + "componentDidUnmount(). But there is no such lifecycle method. " + + "Did you mean componentWillUnmount()?", + name + ); + } - if (queue === null) { - throw new Error( - "Should have a queue. This is likely a bug in React. Please file an issue." - ); - } + if (typeof instance.componentDidReceiveProps === "function") { + 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 + ); + } - queue.lastRenderedReducer = reducer; // This is a re-render. Apply the new render phase updates to the previous - // work-in-progress hook. + if (typeof instance.componentWillRecieveProps === "function") { + error( + "%s has a method called " + + "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", + name + ); + } - var dispatch = queue.dispatch; - var lastRenderPhaseUpdate = queue.pending; - var newState = hook.memoizedState; + if (typeof instance.UNSAFE_componentWillRecieveProps === "function") { + error( + "%s has a method called " + + "UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?", + name + ); + } - if (lastRenderPhaseUpdate !== null) { - // The queue doesn't persist past this render pass. - queue.pending = null; - var firstRenderPhaseUpdate = lastRenderPhaseUpdate.next; - var update = firstRenderPhaseUpdate; + var hasMutatedProps = instance.props !== newProps; - do { - // Process this render phase update. We don't have to check the - // priority because it will always be the same as the current - // render's. - var action = update.action; - newState = reducer(newState, action); - update = update.next; - } while (update !== firstRenderPhaseUpdate); // Mark that the fiber performed work, but only if the new state is - // different from the current state. + if (instance.props !== undefined && hasMutatedProps) { + error( + "%s(...): When calling super() in `%s`, make sure to pass " + + "up the same props that your component's constructor was passed.", + name, + name + ); + } - if (!objectIs(newState, hook.memoizedState)) { - markWorkInProgressReceivedUpdate(); - } + if (instance.defaultProps) { + 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 + ); + } - hook.memoizedState = newState; // Don't persist the state accumulated from the render phase updates to - // the base state unless the queue is empty. - // TODO: Not sure if this is the desired semantics, but it's what we - // do for gDSFP. I can't remember why. + if ( + typeof instance.getSnapshotBeforeUpdate === "function" && + typeof instance.componentDidUpdate !== "function" && + !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor) + ) { + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor); - if (hook.baseQueue === null) { - hook.baseState = newState; - } + error( + "%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). " + + "This component defines getSnapshotBeforeUpdate() only.", + getComponentNameFromType(ctor) + ); + } - queue.lastRenderedState = newState; - } + if (typeof instance.getDerivedStateFromProps === "function") { + error( + "%s: getDerivedStateFromProps() is defined as an instance method " + + "and will be ignored. Instead, declare it as a static method.", + name + ); + } - return [newState, dispatch]; -} + if (typeof instance.getDerivedStateFromError === "function") { + error( + "%s: getDerivedStateFromError() is defined as an instance method " + + "and will be ignored. Instead, declare it as a static method.", + name + ); + } -function mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { - var fiber = currentlyRenderingFiber$1; - var hook = mountWorkInProgressHook(); - var nextSnapshot; + if (typeof ctor.getSnapshotBeforeUpdate === "function") { + error( + "%s: getSnapshotBeforeUpdate() is defined as a static method " + + "and will be ignored. Instead, declare it as an instance method.", + name + ); + } - { - nextSnapshot = getSnapshot(); + var state = instance.state; - { - if (!didWarnUncachedGetSnapshot) { - var cachedSnapshot = getSnapshot(); + if (state && (typeof state !== "object" || isArray(state))) { + error("%s.state: must be set to an object or null", name); + } - if (!objectIs(nextSnapshot, cachedSnapshot)) { + if ( + typeof instance.getChildContext === "function" && + typeof ctor.childContextTypes !== "object" + ) { error( - "The result of getSnapshot should be cached to avoid an infinite loop" + "%s.getChildContext(): childContextTypes must be defined in order to " + + "use getChildContext().", + name ); - - didWarnUncachedGetSnapshot = true; } } - } // Unless we're rendering a blocking lane, schedule a consistency check. - // Right before committing, we will walk the tree and check if any of the - // stores were mutated. - // - // We won't do this if we're hydrating server-rendered content, because if - // the content is stale, it's already visible anyway. Instead we'll patch - // it up in a passive effect. - - var root = getWorkInProgressRoot(); - - if (root === null) { - throw new Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." - ); } - var rootRenderLanes = getWorkInProgressRootRenderLanes(); - - if (!includesBlockingLane(root, rootRenderLanes)) { - pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); - } - } // Read the current snapshot from the store on every render. This breaks the - // normal rules of React, and only works because store updates are - // always synchronous. - - hook.memoizedState = nextSnapshot; - var inst = { - value: nextSnapshot, - getSnapshot: getSnapshot - }; - hook.queue = inst; // Schedule an effect to subscribe to the store. - - mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]); // Schedule an effect to update the mutable instance fields. We will update - // this whenever subscribe, getSnapshot, or value changes. Because there's no - // clean-up function, and we track the deps correctly, we can call pushEffect - // directly, without storing any additional state. For the same reason, we - // don't need to set a static flag, either. - - fiber.flags |= Passive$1; - pushEffect( - HasEffect | Passive, - updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), - createEffectInstance(), - null - ); - return nextSnapshot; -} - -function updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { - var fiber = currentlyRenderingFiber$1; - var hook = updateWorkInProgressHook(); // Read the current snapshot from the store on every render. This breaks the - // normal rules of React, and only works because store updates are - // always synchronous. + function adoptClassInstance(workInProgress, instance) { + instance.updater = classComponentUpdater; + workInProgress.stateNode = instance; // The instance needs access to the fiber so that it can schedule updates - var nextSnapshot; + set(instance, workInProgress); - { - nextSnapshot = getSnapshot(); + { + instance._reactInternalInstance = fakeInternalInstance; + } + } - { - if (!didWarnUncachedGetSnapshot) { - var cachedSnapshot = getSnapshot(); + function constructClassInstance(workInProgress, ctor, props) { + var context = emptyContextObject; + var contextType = ctor.contextType; - if (!objectIs(nextSnapshot, cachedSnapshot)) { - error( - "The result of getSnapshot should be cached to avoid an infinite loop" - ); + { + if ("contextType" in ctor) { + var isValid = // Allow null for conditional declaration + contextType === null || + (contextType !== undefined && + contextType.$$typeof === REACT_CONTEXT_TYPE && + contextType._context === undefined); // Not a + + if (!isValid && !didWarnAboutInvalidateContextType.has(ctor)) { + didWarnAboutInvalidateContextType.add(ctor); + var addendum = ""; + + if (contextType === undefined) { + 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."; + } else if (typeof contextType !== "object") { + addendum = " However, it is set to a " + typeof contextType + "."; + } else if (contextType.$$typeof === REACT_PROVIDER_TYPE) { + addendum = + " Did you accidentally pass the Context.Provider instead?"; + } else if (contextType._context !== undefined) { + // + addendum = + " Did you accidentally pass the Context.Consumer instead?"; + } else { + addendum = + " However, it is set to an object with keys {" + + Object.keys(contextType).join(", ") + + "}."; + } - didWarnUncachedGetSnapshot = true; + error( + "%s defines an invalid contextType. " + + "contextType should point to the Context object returned by React.createContext().%s", + getComponentNameFromType(ctor) || "Component", + addendum + ); + } } } - } - } - - var prevSnapshot = (currentHook || hook).memoizedState; - var snapshotChanged = !objectIs(prevSnapshot, nextSnapshot); - if (snapshotChanged) { - hook.memoizedState = nextSnapshot; - markWorkInProgressReceivedUpdate(); - } - - var inst = hook.queue; - updateEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [ - subscribe - ]); // Whenever getSnapshot or subscribe changes, we need to check in the - // commit phase if there was an interleaved mutation. In concurrent mode - // this can happen all the time, but even in synchronous mode, an earlier - // effect may have mutated the store. + if (typeof contextType === "object" && contextType !== null) { + context = readContext(contextType); + } - if ( - inst.getSnapshot !== getSnapshot || - snapshotChanged || // Check if the subscribe function changed. We can save some memory by - // checking whether we scheduled a subscription effect above. - (workInProgressHook !== null && - workInProgressHook.memoizedState.tag & HasEffect) - ) { - fiber.flags |= Passive$1; - pushEffect( - HasEffect | Passive, - updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), - createEffectInstance(), - null - ); // Unless we're rendering a blocking lane, schedule a consistency check. - // Right before committing, we will walk the tree and check if any of the - // stores were mutated. + var instance = new ctor(props, context); // Instantiate twice to help detect side-effects. - var root = getWorkInProgressRoot(); + { + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); - if (root === null) { - throw new Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." - ); - } + try { + instance = new ctor(props, context); // eslint-disable-line no-new + } finally { + setIsStrictModeForDevtools(false); + } + } + } - if (!includesBlockingLane(root, renderLanes)) { - pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); - } - } + var state = (workInProgress.memoizedState = + instance.state !== null && instance.state !== undefined + ? instance.state + : null); + adoptClassInstance(workInProgress, instance); - return nextSnapshot; -} + { + if ( + typeof ctor.getDerivedStateFromProps === "function" && + state === null + ) { + var componentName = getComponentNameFromType(ctor) || "Component"; -function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) { - fiber.flags |= StoreConsistency; - var check = { - getSnapshot: getSnapshot, - value: renderedSnapshot - }; - var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; - - if (componentUpdateQueue === null) { - componentUpdateQueue = createFunctionComponentUpdateQueue(); - currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; - componentUpdateQueue.stores = [check]; - } else { - var stores = componentUpdateQueue.stores; - - if (stores === null) { - componentUpdateQueue.stores = [check]; - } else { - stores.push(check); - } - } -} + if (!didWarnAboutUninitializedState.has(componentName)) { + didWarnAboutUninitializedState.add(componentName); -function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) { - // These are updated in the passive phase - inst.value = nextSnapshot; - inst.getSnapshot = getSnapshot; // Something may have been mutated in between render and commit. This could - // have been in an event that fired before the passive effects, or it could - // have been in a layout effect. In that case, we would have used the old - // snapsho and getSnapshot values to bail out. We need to check one more time. - - if (checkIfSnapshotChanged(inst)) { - // Force a re-render. - forceStoreRerender(fiber); - } -} + 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 + ); + } + } // If new component APIs are defined, "unsafe" lifecycles won't be called. + // Warn about these lifecycles if they are present. + // Don't warn about react-lifecycles-compat polyfilled methods though. -function subscribeToStore(fiber, inst, subscribe) { - var handleStoreChange = function () { - // The store changed. Check if the snapshot changed since the last time we - // read from the store. - if (checkIfSnapshotChanged(inst)) { - // Force a re-render. - forceStoreRerender(fiber); - } - }; // Subscribe to the store and return a clean-up function. + if ( + typeof ctor.getDerivedStateFromProps === "function" || + typeof instance.getSnapshotBeforeUpdate === "function" + ) { + var foundWillMountName = null; + var foundWillReceivePropsName = null; + var foundWillUpdateName = null; - return subscribe(handleStoreChange); -} + if ( + typeof instance.componentWillMount === "function" && + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + foundWillMountName = "componentWillMount"; + } else if (typeof instance.UNSAFE_componentWillMount === "function") { + foundWillMountName = "UNSAFE_componentWillMount"; + } -function checkIfSnapshotChanged(inst) { - var latestGetSnapshot = inst.getSnapshot; - var prevValue = inst.value; + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== + true + ) { + foundWillReceivePropsName = "componentWillReceiveProps"; + } else if ( + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + foundWillReceivePropsName = "UNSAFE_componentWillReceiveProps"; + } - try { - var nextValue = latestGetSnapshot(); - return !objectIs(prevValue, nextValue); - } catch (error) { - return true; - } -} + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + foundWillUpdateName = "componentWillUpdate"; + } else if ( + typeof instance.UNSAFE_componentWillUpdate === "function" + ) { + foundWillUpdateName = "UNSAFE_componentWillUpdate"; + } -function forceStoreRerender(fiber) { - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + if ( + foundWillMountName !== null || + foundWillReceivePropsName !== null || + foundWillUpdateName !== null + ) { + var _componentName = getComponentNameFromType(ctor) || "Component"; - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } -} + var newApiName = + typeof ctor.getDerivedStateFromProps === "function" + ? "getDerivedStateFromProps()" + : "getSnapshotBeforeUpdate()"; -function mountStateImpl(initialState) { - var hook = mountWorkInProgressHook(); - - if (typeof initialState === "function") { - // $FlowFixMe[incompatible-use]: Flow doesn't like mixed types - initialState = initialState(); - } - - hook.memoizedState = hook.baseState = initialState; - var queue = { - pending: null, - lanes: NoLanes, - dispatch: null, - lastRenderedReducer: basicStateReducer, - lastRenderedState: initialState - }; - hook.queue = queue; - return hook; -} + if ( + !didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName) + ) { + didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName); -function mountState(initialState) { - var hook = mountStateImpl(initialState); - var queue = hook.queue; - var dispatch = dispatchSetState.bind(null, currentlyRenderingFiber$1, queue); - queue.dispatch = dispatch; - return [hook.memoizedState, dispatch]; -} + 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 : "" + ); + } + } + } + } // Cache unmasked context so we can avoid recreating masked context unless necessary. -function updateState(initialState) { - return updateReducer(basicStateReducer); -} + return instance; + } -function rerenderState(initialState) { - return rerenderReducer(basicStateReducer); -} + function callComponentWillMount(workInProgress, instance) { + var oldState = instance.state; -function mountOptimistic(passthrough, reducer) { - var hook = mountWorkInProgressHook(); - hook.memoizedState = hook.baseState = passthrough; - var queue = { - pending: null, - lanes: NoLanes, - dispatch: null, - // Optimistic state does not use the eager update optimization. - lastRenderedReducer: null, - lastRenderedState: null - }; - hook.queue = queue; // This is different than the normal setState function. - - var dispatch = dispatchOptimisticSetState.bind( - null, - currentlyRenderingFiber$1, - true, - queue - ); - queue.dispatch = dispatch; - return [passthrough, dispatch]; -} + if (typeof instance.componentWillMount === "function") { + instance.componentWillMount(); + } -function updateOptimistic(passthrough, reducer) { - var hook = updateWorkInProgressHook(); - return updateOptimisticImpl(hook, currentHook, passthrough, reducer); -} + if (typeof instance.UNSAFE_componentWillMount === "function") { + instance.UNSAFE_componentWillMount(); + } -function updateOptimisticImpl(hook, current, passthrough, reducer) { - // Optimistic updates are always rebased on top of the latest value passed in - // as an argument. It's called a passthrough because if there are no pending - // updates, it will be returned as-is. - // - // Reset the base state to the passthrough. Future updates will be applied - // on top of this. - hook.baseState = passthrough; // If a reducer is not provided, default to the same one used by useState. - - var resolvedReducer = - typeof reducer === "function" ? reducer : basicStateReducer; - return updateReducerImpl(hook, currentHook, resolvedReducer); -} + if (oldState !== instance.state) { + { + error( + "%s.componentWillMount(): Assigning directly to this.state is " + + "deprecated (except inside a component's " + + "constructor). Use setState instead.", + getComponentNameFromFiber(workInProgress) || "Component" + ); + } -function rerenderOptimistic(passthrough, reducer) { - // Unlike useState, useOptimistic doesn't support render phase updates. - // Also unlike useState, we need to replay all pending updates again in case - // the passthrough value changed. - // - // So instead of a forked re-render implementation that knows how to handle - // render phase udpates, we can use the same implementation as during a - // regular mount or update. - var hook = updateWorkInProgressHook(); - - if (currentHook !== null) { - // This is an update. Process the update queue. - return updateOptimisticImpl(hook, currentHook, passthrough, reducer); - } // This is a mount. No updates to process. - // Reset the base state to the passthrough. Future updates will be applied - // on top of this. - - hook.baseState = passthrough; - var dispatch = hook.queue.dispatch; - return [passthrough, dispatch]; -} // useFormState actions run sequentially, because each action receives the - -function pushEffect(tag, create, inst, deps) { - var effect = { - tag: tag, - create: create, - inst: inst, - deps: deps, - // Circular - next: null - }; - var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; - - if (componentUpdateQueue === null) { - componentUpdateQueue = createFunctionComponentUpdateQueue(); - currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; - componentUpdateQueue.lastEffect = effect.next = effect; - } else { - var lastEffect = componentUpdateQueue.lastEffect; - - if (lastEffect === null) { - componentUpdateQueue.lastEffect = effect.next = effect; - } else { - var firstEffect = lastEffect.next; - lastEffect.next = effect; - effect.next = firstEffect; - componentUpdateQueue.lastEffect = effect; + classComponentUpdater.enqueueReplaceState( + instance, + instance.state, + null + ); + } } - } - return effect; -} + function callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + nextContext + ) { + var oldState = instance.state; -function createEffectInstance() { - return { - destroy: undefined - }; -} + if (typeof instance.componentWillReceiveProps === "function") { + instance.componentWillReceiveProps(newProps, nextContext); + } -var stackContainsErrorMessage = null; + if (typeof instance.UNSAFE_componentWillReceiveProps === "function") { + instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); + } -function getCallerStackFrame() { - // eslint-disable-next-line react-internal/prod-error-codes - var stackFrames = new Error("Error message").stack.split("\n"); // Some browsers (e.g. Chrome) include the error message in the stack - // but others (e.g. Firefox) do not. + if (instance.state !== oldState) { + { + var componentName = + getComponentNameFromFiber(workInProgress) || "Component"; - if (stackContainsErrorMessage === null) { - stackContainsErrorMessage = stackFrames[0].includes("Error message"); - } + if (!didWarnAboutStateAssignmentForComponent.has(componentName)) { + didWarnAboutStateAssignmentForComponent.add(componentName); - return stackContainsErrorMessage - ? stackFrames.slice(3, 4).join("\n") - : stackFrames.slice(2, 3).join("\n"); -} + error( + "%s.componentWillReceiveProps(): Assigning directly to " + + "this.state is deprecated (except inside a component's " + + "constructor). Use setState instead.", + componentName + ); + } + } -function mountRef(initialValue) { - var hook = mountWorkInProgressHook(); + classComponentUpdater.enqueueReplaceState( + instance, + instance.state, + null + ); + } + } // Invokes the mount life-cycles on a previously never rendered instance. - if (enableUseRefAccessWarning) { - { - // Support lazy initialization pattern shown in docs. - // We need to store the caller stack frame so that we don't warn on subsequent renders. - var hasBeenInitialized = initialValue != null; - var lazyInitGetterStack = null; - var didCheckForLazyInit = false; // Only warn once per component+hook. - - var didWarnAboutRead = false; - var didWarnAboutWrite = false; - var current = initialValue; - var ref = { - get current() { - if (!hasBeenInitialized) { - didCheckForLazyInit = true; - lazyInitGetterStack = getCallerStackFrame(); - } else if (currentlyRenderingFiber$1 !== null && !didWarnAboutRead) { - if ( - lazyInitGetterStack === null || - lazyInitGetterStack !== getCallerStackFrame() - ) { - didWarnAboutRead = true; + function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { + { + checkClassInstance(workInProgress, ctor, newProps); + } - warn( - "%s: Unsafe read of a mutable value during render.\n\n" + - "Reading from a ref during render is only safe if:\n" + - "1. The ref value has not been updated, or\n" + - "2. The ref holds a lazily-initialized value that is only set once.\n", - getComponentNameFromFiber(currentlyRenderingFiber$1) || - "Unknown" - ); - } - } + var instance = workInProgress.stateNode; + instance.props = newProps; + instance.state = workInProgress.memoizedState; + instance.refs = {}; + initializeUpdateQueue(workInProgress); + var contextType = ctor.contextType; - return current; - }, + if (typeof contextType === "object" && contextType !== null) { + instance.context = readContext(contextType); + } else { + instance.context = emptyContextObject; + } - set current(value) { - if (currentlyRenderingFiber$1 !== null && !didWarnAboutWrite) { - if (hasBeenInitialized || !didCheckForLazyInit) { - didWarnAboutWrite = true; + { + if (instance.state === newProps) { + var componentName = getComponentNameFromType(ctor) || "Component"; - warn( - "%s: Unsafe write of a mutable value during render.\n\n" + - "Writing to a ref during render is only safe if the ref holds " + - "a lazily-initialized value that is only set once.\n", - getComponentNameFromFiber(currentlyRenderingFiber$1) || - "Unknown" - ); - } + if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) { + didWarnAboutDirectlyAssigningPropsToState.add(componentName); + + 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 + ); } + } - hasBeenInitialized = true; - current = value; + if (workInProgress.mode & StrictLegacyMode) { + ReactStrictModeWarnings.recordLegacyContextWarning( + workInProgress, + instance + ); } - }; - Object.seal(ref); - hook.memoizedState = ref; - return ref; - } - } else { - var _ref2 = { - current: initialValue - }; - hook.memoizedState = _ref2; - return _ref2; - } -} -function updateRef(initialValue) { - var hook = updateWorkInProgressHook(); - return hook.memoizedState; -} + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings( + workInProgress, + instance + ); + } -function mountEffectImpl(fiberFlags, hookFlags, create, deps) { - var hook = mountWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - currentlyRenderingFiber$1.flags |= fiberFlags; - hook.memoizedState = pushEffect( - HasEffect | hookFlags, - create, - createEffectInstance(), - nextDeps - ); -} + instance.state = workInProgress.memoizedState; + var getDerivedStateFromProps = ctor.getDerivedStateFromProps; + + if (typeof getDerivedStateFromProps === "function") { + applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + newProps + ); + instance.state = workInProgress.memoizedState; + } // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. -function updateEffectImpl(fiberFlags, hookFlags, create, deps) { - var hook = updateWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var effect = hook.memoizedState; - var inst = effect.inst; // currentHook is null on initial mount when rerendering after a render phase - // state update or for strict mode. + if ( + typeof ctor.getDerivedStateFromProps !== "function" && + typeof instance.getSnapshotBeforeUpdate !== "function" && + (typeof instance.UNSAFE_componentWillMount === "function" || + typeof instance.componentWillMount === "function") + ) { + callComponentWillMount(workInProgress, instance); // If we had additional state updates during this life-cycle, let's + // process them now. - if (currentHook !== null) { - if (nextDeps !== null) { - var prevEffect = currentHook.memoizedState; - var prevDeps = prevEffect.deps; + processUpdateQueue(workInProgress, newProps, instance, renderLanes); + instance.state = workInProgress.memoizedState; + } - if (areHookInputsEqual(nextDeps, prevDeps)) { - hook.memoizedState = pushEffect(hookFlags, create, inst, nextDeps); - return; + if (typeof instance.componentDidMount === "function") { + workInProgress.flags |= Update | LayoutStatic; + } + + if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { + workInProgress.flags |= MountLayoutDev; } } - } - currentlyRenderingFiber$1.flags |= fiberFlags; - hook.memoizedState = pushEffect( - HasEffect | hookFlags, - create, - inst, - nextDeps - ); -} + function resumeMountClassInstance( + workInProgress, + ctor, + newProps, + renderLanes + ) { + var instance = workInProgress.stateNode; + var oldProps = workInProgress.memoizedProps; + instance.props = oldProps; + var oldContext = instance.context; + var contextType = ctor.contextType; + var nextContext = emptyContextObject; + + if (typeof contextType === "object" && contextType !== null) { + nextContext = readContext(contextType); + } + + var getDerivedStateFromProps = ctor.getDerivedStateFromProps; + var hasNewLifecycles = + typeof getDerivedStateFromProps === "function" || + typeof instance.getSnapshotBeforeUpdate === "function"; // Note: During these life-cycles, instance.props/instance.state are what + // ever the previously attempted to render - not the "current". However, + // during componentDidUpdate we pass the "current" props. + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. -function mountEffect(create, deps) { - if ( - (currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode && - (currentlyRenderingFiber$1.mode & NoStrictPassiveEffectsMode) === NoMode - ) { - mountEffectImpl( - MountPassiveDev | Passive$1 | PassiveStatic, - Passive, - create, - deps - ); - } else { - mountEffectImpl(Passive$1 | PassiveStatic, Passive, create, deps); - } -} + if ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillReceiveProps === "function" || + typeof instance.componentWillReceiveProps === "function") + ) { + if (oldProps !== newProps || oldContext !== nextContext) { + callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + nextContext + ); + } + } -function updateEffect(create, deps) { - updateEffectImpl(Passive$1, Passive, create, deps); -} + resetHasForceUpdateBeforeProcessing(); + var oldState = workInProgress.memoizedState; + var newState = (instance.state = oldState); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); + newState = workInProgress.memoizedState; -function useEffectEventImpl(payload) { - currentlyRenderingFiber$1.flags |= Update; - var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; + if ( + oldProps === newProps && + oldState === newState && + !hasContextChanged() && + !checkHasForceUpdateAfterProcessing() + ) { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidMount === "function") { + workInProgress.flags |= Update | LayoutStatic; + } - if (componentUpdateQueue === null) { - componentUpdateQueue = createFunctionComponentUpdateQueue(); - currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; - componentUpdateQueue.events = [payload]; - } else { - var events = componentUpdateQueue.events; + if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { + workInProgress.flags |= MountLayoutDev; + } - if (events === null) { - componentUpdateQueue.events = [payload]; - } else { - events.push(payload); - } - } -} + return false; + } -function mountEvent(callback) { - var hook = mountWorkInProgressHook(); - var ref = { - impl: callback - }; - hook.memoizedState = ref; // $FlowIgnore[incompatible-return] + if (typeof getDerivedStateFromProps === "function") { + applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + newProps + ); + newState = workInProgress.memoizedState; + } - return function eventFn() { - if (isInvalidExecutionContextForEventFunction()) { - throw new Error( - "A function wrapped in useEffectEvent can't be called during rendering." - ); - } + var shouldUpdate = + checkHasForceUpdateAfterProcessing() || + checkShouldComponentUpdate( + workInProgress, + ctor, + oldProps, + newProps, + oldState, + newState, + nextContext + ); - return ref.impl.apply(undefined, arguments); - }; -} + if (shouldUpdate) { + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. + if ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillMount === "function" || + typeof instance.componentWillMount === "function") + ) { + if (typeof instance.componentWillMount === "function") { + instance.componentWillMount(); + } -function updateEvent(callback) { - var hook = updateWorkInProgressHook(); - var ref = hook.memoizedState; - useEffectEventImpl({ - ref: ref, - nextImpl: callback - }); // $FlowIgnore[incompatible-return] + if (typeof instance.UNSAFE_componentWillMount === "function") { + instance.UNSAFE_componentWillMount(); + } + } - return function eventFn() { - if (isInvalidExecutionContextForEventFunction()) { - throw new Error( - "A function wrapped in useEffectEvent can't be called during rendering." - ); - } + if (typeof instance.componentDidMount === "function") { + workInProgress.flags |= Update | LayoutStatic; + } - return ref.impl.apply(undefined, arguments); - }; -} + if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { + workInProgress.flags |= MountLayoutDev; + } + } else { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidMount === "function") { + workInProgress.flags |= Update | LayoutStatic; + } -function mountInsertionEffect(create, deps) { - mountEffectImpl(Update, Insertion, create, deps); -} + if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { + workInProgress.flags |= MountLayoutDev; + } // If shouldComponentUpdate returned false, we should still update the + // memoized state to indicate that this work can be reused. -function updateInsertionEffect(create, deps) { - return updateEffectImpl(Update, Insertion, create, deps); -} + workInProgress.memoizedProps = newProps; + workInProgress.memoizedState = newState; + } // Update the existing instance's state, props, and context pointers even + // if shouldComponentUpdate returns false. -function mountLayoutEffect(create, deps) { - var fiberFlags = Update | LayoutStatic; + instance.props = newProps; + instance.state = newState; + instance.context = nextContext; + return shouldUpdate; + } // Invokes the update life-cycles and returns false if it shouldn't rerender. - if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { - fiberFlags |= MountLayoutDev; - } + function updateClassInstance( + current, + workInProgress, + ctor, + newProps, + renderLanes + ) { + var instance = workInProgress.stateNode; + cloneUpdateQueue(current, workInProgress); + var unresolvedOldProps = workInProgress.memoizedProps; + var oldProps = + workInProgress.type === workInProgress.elementType + ? unresolvedOldProps + : resolveDefaultProps(workInProgress.type, unresolvedOldProps); + instance.props = oldProps; + var unresolvedNewProps = workInProgress.pendingProps; + var oldContext = instance.context; + var contextType = ctor.contextType; + var nextContext = emptyContextObject; + + if (typeof contextType === "object" && contextType !== null) { + nextContext = readContext(contextType); + } + + var getDerivedStateFromProps = ctor.getDerivedStateFromProps; + var hasNewLifecycles = + typeof getDerivedStateFromProps === "function" || + typeof instance.getSnapshotBeforeUpdate === "function"; // Note: During these life-cycles, instance.props/instance.state are what + // ever the previously attempted to render - not the "current". However, + // during componentDidUpdate we pass the "current" props. + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. - return mountEffectImpl(fiberFlags, Layout, create, deps); -} + if ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillReceiveProps === "function" || + typeof instance.componentWillReceiveProps === "function") + ) { + if ( + unresolvedOldProps !== unresolvedNewProps || + oldContext !== nextContext + ) { + callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + nextContext + ); + } + } -function updateLayoutEffect(create, deps) { - return updateEffectImpl(Update, Layout, create, deps); -} + resetHasForceUpdateBeforeProcessing(); + var oldState = workInProgress.memoizedState; + var newState = (instance.state = oldState); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); + newState = workInProgress.memoizedState; -function imperativeHandleEffect(create, ref) { - if (typeof ref === "function") { - var refCallback = ref; - var inst = create(); - refCallback(inst); - return function () { - refCallback(null); - }; - } else if (ref !== null && ref !== undefined) { - var refObject = ref; + if ( + unresolvedOldProps === unresolvedNewProps && + oldState === newState && + !hasContextChanged() && + !checkHasForceUpdateAfterProcessing() && + !( + enableLazyContextPropagation && + current !== null && + current.dependencies !== null && + checkIfContextChanged(current.dependencies) + ) + ) { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidUpdate === "function") { + if ( + unresolvedOldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.flags |= Update; + } + } - { - if (!refObject.hasOwnProperty("current")) { - 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(", ") + "}" + if (typeof instance.getSnapshotBeforeUpdate === "function") { + if ( + unresolvedOldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.flags |= Snapshot; + } + } + + return false; + } + + if (typeof getDerivedStateFromProps === "function") { + applyDerivedStateFromProps( + workInProgress, + ctor, + getDerivedStateFromProps, + newProps ); + newState = workInProgress.memoizedState; } - } - var _inst = create(); + 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, + // both before and after `shouldComponentUpdate` has been called. Not ideal, + // but I'm loath to refactor this function. This only happens for memoized + // components so it's not that common. + (enableLazyContextPropagation && + current !== null && + current.dependencies !== null && + checkIfContextChanged(current.dependencies)); - refObject.current = _inst; - return function () { - refObject.current = null; - }; - } -} + if (shouldUpdate) { + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. + if ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillUpdate === "function" || + typeof instance.componentWillUpdate === "function") + ) { + if (typeof instance.componentWillUpdate === "function") { + instance.componentWillUpdate(newProps, newState, nextContext); + } -function mountImperativeHandle(ref, create, deps) { - { - if (typeof create !== "function") { - error( - "Expected useImperativeHandle() second argument to be a function " + - "that creates a handle. Instead received: %s.", - create !== null ? typeof create : "null" - ); - } - } // TODO: If deps are provided, should we skip comparing the ref itself? + if (typeof instance.UNSAFE_componentWillUpdate === "function") { + instance.UNSAFE_componentWillUpdate( + newProps, + newState, + nextContext + ); + } + } - var effectDeps = - deps !== null && deps !== undefined ? deps.concat([ref]) : null; - var fiberFlags = Update | LayoutStatic; + if (typeof instance.componentDidUpdate === "function") { + workInProgress.flags |= Update; + } - if ((currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { - fiberFlags |= MountLayoutDev; - } + if (typeof instance.getSnapshotBeforeUpdate === "function") { + workInProgress.flags |= Snapshot; + } + } else { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidUpdate === "function") { + if ( + unresolvedOldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.flags |= Update; + } + } - mountEffectImpl( - fiberFlags, - Layout, - imperativeHandleEffect.bind(null, create, ref), - effectDeps - ); -} + if (typeof instance.getSnapshotBeforeUpdate === "function") { + if ( + unresolvedOldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.flags |= Snapshot; + } + } // If shouldComponentUpdate returned false, we should still update the + // memoized props/state to indicate that this work can be reused. + + workInProgress.memoizedProps = newProps; + workInProgress.memoizedState = newState; + } // Update the existing instance's state, props, and context pointers even + // if shouldComponentUpdate returns false. + + instance.props = newProps; + instance.state = newState; + instance.context = nextContext; + return shouldUpdate; + } + + function createCapturedValueAtFiber(value, source) { + // If the value is an error, call this function immediately after it is thrown + // so the stack is accurate. + return { + value: value, + source: source, + stack: getStackByFiberInDevAndProd(source), + digest: null + }; + } + function createCapturedValue(value, digest, stack) { + return { + value: value, + source: null, + stack: stack != null ? stack : null, + digest: digest != null ? digest : null + }; + } + + var ReactFiberErrorDialogWWW = require("ReactFiberErrorDialog"); -function updateImperativeHandle(ref, create, deps) { - { - if (typeof create !== "function") { - error( - "Expected useImperativeHandle() second argument to be a function " + - "that creates a handle. Instead received: %s.", - create !== null ? typeof create : "null" + if (typeof ReactFiberErrorDialogWWW.showErrorDialog !== "function") { + throw new Error( + "Expected ReactFiberErrorDialog.showErrorDialog to be a function." ); } - } // TODO: If deps are provided, should we skip comparing the ref itself? - - var effectDeps = - deps !== null && deps !== undefined ? deps.concat([ref]) : null; - updateEffectImpl( - Update, - Layout, - imperativeHandleEffect.bind(null, create, ref), - effectDeps - ); -} -function mountDebugValue(value, formatterFn) { - // This hook is normally a no-op. - // The react-debug-hooks package injects its own implementation - // so that e.g. DevTools can display custom hook values. -} + function showErrorDialog(boundary, errorInfo) { + var capturedError = { + componentStack: errorInfo.stack !== null ? errorInfo.stack : "", + error: errorInfo.value, + errorBoundary: + boundary !== null && boundary.tag === ClassComponent + ? boundary.stateNode + : null + }; + return ReactFiberErrorDialogWWW.showErrorDialog(capturedError); + } -var updateDebugValue = mountDebugValue; + function logCapturedError(boundary, errorInfo) { + try { + var logError = showErrorDialog(boundary, errorInfo); // Allow injected showErrorDialog() to prevent default console.error logging. + // This enables renderers like ReactNative to better manage redbox behavior. -function mountCallback(callback, deps) { - var hook = mountWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - hook.memoizedState = [callback, nextDeps]; - return callback; -} + if (logError === false) { + return; + } -function updateCallback(callback, deps) { - var hook = updateWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var prevState = hook.memoizedState; + var error = errorInfo.value; - if (nextDeps !== null) { - var prevDeps = prevState[1]; + if (true) { + var source = errorInfo.source; + var stack = errorInfo.stack; + var componentStack = stack !== null ? stack : ""; // Browsers support silencing uncaught errors by calling + // `preventDefault()` in window `error` handler. + // We record this information as an expando on the error. - if (areHookInputsEqual(nextDeps, prevDeps)) { - return prevState[0]; - } - } + if (error != null && error._suppressLogging) { + if (boundary.tag === ClassComponent) { + // The error is recoverable and was silenced. + // Ignore it and don't print the stack addendum. + // This is handy for testing error boundaries without noise. + return; + } // The error is fatal. Since the silencing might have + // been accidental, we'll surface it anyway. + // However, the browser would have silenced the original error + // so we'll print it first, and then print the stack addendum. + + console["error"](error); // Don't transform to our wrapper + // For a more detailed description of this block, see: + // https://github.com/facebook/react/pull/13384 + } - hook.memoizedState = [callback, nextDeps]; - return callback; -} + var componentName = source ? getComponentNameFromFiber(source) : null; + var componentNameMessage = componentName + ? "The above error occurred in the <" + + componentName + + "> component:" + : "The above error occurred in one of your React components:"; + var errorBoundaryMessage; + + if (boundary.tag === HostRoot) { + 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."; + } else { + var errorBoundaryName = + getComponentNameFromFiber(boundary) || "Anonymous"; + errorBoundaryMessage = + "React will try to recreate this component tree from scratch " + + ("using the error boundary you provided, " + + errorBoundaryName + + "."); + } -function mountMemo(nextCreate, deps) { - var hook = mountWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; + var combinedMessage = + componentNameMessage + + "\n" + + componentStack + + "\n\n" + + ("" + errorBoundaryMessage); // In development, we provide our own message with just the component stack. + // We don't include the original error message and JS stack because the browser + // has already printed it. Even if the application swallows the error, it is still + // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils. + + console["error"](combinedMessage); // Don't transform to our wrapper + } + } catch (e) { + // This method must not throw, or React internal state will get messed up. + // If console.error is overridden, or logCapturedError() shows a dialog that throws, + // we want to report this error outside of the normal stack as a last resort. + // https://github.com/facebook/react/issues/13188 + setTimeout(function () { + throw e; + }); + } + } - if (shouldDoubleInvokeUserFnsInHooksDEV) { - nextCreate(); - } + function createRootErrorUpdate(fiber, errorInfo, lane) { + var update = createUpdate(lane); // Unmount the root by rendering null. - var nextValue = nextCreate(); - hook.memoizedState = [nextValue, nextDeps]; - return nextValue; -} + update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property + // being called "element". -function updateMemo(nextCreate, deps) { - var hook = updateWorkInProgressHook(); - var nextDeps = deps === undefined ? null : deps; - var prevState = hook.memoizedState; // Assume these are defined. If they're not, areHookInputsEqual will warn. + update.payload = { + element: null + }; + var error = errorInfo.value; - if (nextDeps !== null) { - var prevDeps = prevState[1]; + update.callback = function () { + onUncaughtError(error); + logCapturedError(fiber, errorInfo); + }; - if (areHookInputsEqual(nextDeps, prevDeps)) { - return prevState[0]; + return update; } - } - - if (shouldDoubleInvokeUserFnsInHooksDEV) { - nextCreate(); - } - - var nextValue = nextCreate(); - hook.memoizedState = [nextValue, nextDeps]; - return nextValue; -} -function mountDeferredValue(value, initialValue) { - var hook = mountWorkInProgressHook(); - return mountDeferredValueImpl(hook, value, initialValue); -} + function createClassErrorUpdate(fiber, errorInfo, lane) { + var update = createUpdate(lane); + update.tag = CaptureUpdate; + var getDerivedStateFromError = fiber.type.getDerivedStateFromError; -function updateDeferredValue(value, initialValue) { - var hook = updateWorkInProgressHook(); - var resolvedCurrentHook = currentHook; - var prevValue = resolvedCurrentHook.memoizedState; - return updateDeferredValueImpl(hook, prevValue, value, initialValue); -} + if (typeof getDerivedStateFromError === "function") { + var error$1 = errorInfo.value; -function rerenderDeferredValue(value, initialValue) { - var hook = updateWorkInProgressHook(); - - if (currentHook === null) { - // This is a rerender during a mount. - return mountDeferredValueImpl(hook, value, initialValue); - } else { - // This is a rerender during an update. - var prevValue = currentHook.memoizedState; - return updateDeferredValueImpl(hook, prevValue, value, initialValue); - } -} + update.payload = function () { + return getDerivedStateFromError(error$1); + }; -function mountDeferredValueImpl(hook, value, initialValue) { - if ( - enableUseDeferredValueInitialArg && // When `initialValue` is provided, we defer the initial render even if the - // current render is not synchronous. - initialValue !== undefined && // However, to avoid waterfalls, we do not defer if this render - // was itself spawned by an earlier useDeferredValue. Check if DeferredLane - // is part of the render lanes. - !includesSomeLane(renderLanes, DeferredLane) - ) { - // Render with the initial value - hook.memoizedState = initialValue; // Schedule a deferred render to switch to the final value. - - var deferredLane = requestDeferredLane(); - currentlyRenderingFiber$1.lanes = mergeLanes( - currentlyRenderingFiber$1.lanes, - deferredLane - ); - markSkippedUpdateLanes(deferredLane); - return initialValue; - } else { - hook.memoizedState = value; - return value; - } -} + update.callback = function () { + { + markFailedErrorBoundaryForHotReloading(fiber); + } -function updateDeferredValueImpl(hook, prevValue, value, initialValue) { - if (objectIs(value, prevValue)) { - // The incoming value is referentially identical to the currently rendered - // value, so we can bail out quickly. - return value; - } else { - // Received a new value that's different from the current value. - // Check if we're inside a hidden tree - if (isCurrentTreeHidden()) { - // Revealing a prerendered tree is considered the same as mounting new - // one, so we reuse the "mount" path in this case. - var resultValue = mountDeferredValueImpl(hook, value, initialValue); // Unlike during an actual mount, we need to mark this as an update if - // the value changed. - - if (!objectIs(resultValue, prevValue)) { - markWorkInProgressReceivedUpdate(); + logCapturedError(fiber, errorInfo); + }; } - return resultValue; - } + var inst = fiber.stateNode; - var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes); + if (inst !== null && typeof inst.componentDidCatch === "function") { + // $FlowFixMe[missing-this-annot] + update.callback = function callback() { + { + markFailedErrorBoundaryForHotReloading(fiber); + } - if (shouldDeferValue) { - // This is an urgent update. Since the value has changed, keep using the - // previous value and spawn a deferred render to update it later. - // Schedule a deferred render - var deferredLane = requestDeferredLane(); - currentlyRenderingFiber$1.lanes = mergeLanes( - currentlyRenderingFiber$1.lanes, - deferredLane - ); - markSkippedUpdateLanes(deferredLane); // Reuse the previous value. We do not need to mark this as an update, - // because we did not render a new value. + logCapturedError(fiber, errorInfo); - return prevValue; - } else { - // This is not an urgent update, so we can use the latest value regardless - // of what it is. No need to defer it. - // Mark this as an update to prevent the fiber from bailing out. - markWorkInProgressReceivedUpdate(); - hook.memoizedState = value; - return value; - } - } -} + if (typeof getDerivedStateFromError !== "function") { + // To preserve the preexisting retry behavior of error boundaries, + // we keep track of which ones already failed during this batch. + // This gets reset before we yield back to the browser. + // TODO: Warn in strict mode if getDerivedStateFromError is + // not defined. + markLegacyErrorBoundaryAsFailed(this); + } -function startTransition( - fiber, - queue, - pendingState, - finishedState, - callback, - options -) { - var previousPriority = getCurrentUpdatePriority(); - setCurrentUpdatePriority( - higherEventPriority(previousPriority, ContinuousEventPriority) - ); - var prevTransition = ReactCurrentBatchConfig$2.transition; - var currentTransition = {}; - - if (enableAsyncActions) { - // We don't really need to use an optimistic update here, because we - // schedule a second "revert" update below (which we use to suspend the - // transition until the async action scope has finished). But we'll use an - // optimistic update anyway to make it less likely the behavior accidentally - // diverges; for example, both an optimistic update and this one should - // share the same lane. - ReactCurrentBatchConfig$2.transition = currentTransition; - dispatchOptimisticSetState(fiber, false, queue, pendingState); - } else { - ReactCurrentBatchConfig$2.transition = null; - dispatchSetState(fiber, queue, pendingState); - ReactCurrentBatchConfig$2.transition = currentTransition; - } - - if (enableTransitionTracing) { - if (options !== undefined && options.name !== undefined) { - ReactCurrentBatchConfig$2.transition.name = options.name; - ReactCurrentBatchConfig$2.transition.startTime = now$1(); - } - } - - { - ReactCurrentBatchConfig$2.transition._updatedFibers = new Set(); - } - - try { - if (enableAsyncActions) { - var returnValue = callback(); // Check if we're inside an async action scope. If so, we'll entangle - // this new action with the existing scope. - // - // If we're not already inside an async action scope, and this action is - // async, then we'll create a new async scope. - // - // In the async case, the resulting render will suspend until the async - // action scope has finished. + var error$1 = errorInfo.value; + var stack = errorInfo.stack; + this.componentDidCatch(error$1, { + componentStack: stack !== null ? stack : "" + }); + + { + if (typeof getDerivedStateFromError !== "function") { + // If componentDidCatch is the only error boundary method defined, + // then it needs to call setState to recover from errors. + // If no state update is scheduled then the boundary will swallow the error. + if (!includesSomeLane(fiber.lanes, SyncLane)) { + 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" + ); + } + } + } + }; + } - if ( - returnValue !== null && - typeof returnValue === "object" && - typeof returnValue.then === "function" - ) { - var thenable = returnValue; // This is a thenable that resolves to `finishedState` once the async - // action scope has finished. + return update; + } - var entangledResult = requestAsyncActionContext( - thenable, - finishedState - ); - dispatchSetState(fiber, queue, entangledResult); - } else { - // This is either `finishedState` or a thenable that resolves to - // `finishedState`, depending on whether we're inside an async - // action scope. - var _entangledResult2 = requestSyncActionContext( - returnValue, - finishedState - ); + function resetSuspendedComponent(sourceFiber, rootRenderLanes) { + if (enableLazyContextPropagation) { + var currentSourceFiber = sourceFiber.alternate; - dispatchSetState(fiber, queue, _entangledResult2); - } - } else { - // Async actions are not enabled. - dispatchSetState(fiber, queue, finishedState); - callback(); - } - } catch (error) { - if (enableAsyncActions) { - // This is a trick to get the `useTransition` hook to rethrow the error. - // When it unwraps the thenable with the `use` algorithm, the error - // will be thrown. - var rejectedThenable = { - then: function () {}, - status: "rejected", - reason: error - }; - dispatchSetState(fiber, queue, rejectedThenable); - } else { - // The error rethrowing behavior is only enabled when the async actions - // feature is on, even for sync actions. - throw error; - } - } finally { - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig$2.transition = prevTransition; + if (currentSourceFiber !== null) { + // Since we never visited the children of the suspended component, we + // need to propagate the context change now, to ensure that we visit + // them during the retry. + // + // We don't have to do this for errors because we retry errors without + // committing in between. So this is specific to Suspense. + propagateParentContextChangesToDeferredTree( + currentSourceFiber, + sourceFiber, + rootRenderLanes + ); + } + } // Reset the memoizedState to what it was before we attempted to render it. + // A legacy mode Suspense quirk, only relevant to hook components. - { - if (prevTransition === null && currentTransition._updatedFibers) { - var updatedFibersCount = currentTransition._updatedFibers.size; + var tag = sourceFiber.tag; - currentTransition._updatedFibers.clear(); + if ( + (sourceFiber.mode & ConcurrentMode) === NoMode && + (tag === FunctionComponent || + tag === ForwardRef || + tag === SimpleMemoComponent) + ) { + var currentSource = sourceFiber.alternate; - if (updatedFibersCount > 10) { - 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." - ); + if (currentSource) { + sourceFiber.updateQueue = currentSource.updateQueue; + sourceFiber.memoizedState = currentSource.memoizedState; + sourceFiber.lanes = currentSource.lanes; + } else { + sourceFiber.updateQueue = null; + sourceFiber.memoizedState = null; } } } - } -} - -function mountTransition() { - var stateHook = mountStateImpl(false); // The `start` method never changes. - - var start = startTransition.bind( - null, - currentlyRenderingFiber$1, - stateHook.queue, - true, - false - ); - var hook = mountWorkInProgressHook(); - hook.memoizedState = start; - return [false, start]; -} -function updateTransition() { - var _updateState = updateState(), - booleanOrThenable = _updateState[0]; - - var hook = updateWorkInProgressHook(); - var start = hook.memoizedState; - var isPending = - typeof booleanOrThenable === "boolean" - ? booleanOrThenable // This will suspend until the async action scope has finished. - : useThenable(booleanOrThenable); - return [isPending, start]; -} + function markSuspenseBoundaryShouldCapture( + suspenseBoundary, + returnFiber, + sourceFiber, + root, + rootRenderLanes + ) { + // This marks a Suspense boundary so that when we're unwinding the stack, + // it captures the suspended "exception" and does a second (fallback) pass. + if ((suspenseBoundary.mode & ConcurrentMode) === NoMode) { + // Legacy Mode Suspense + // + // If the boundary is in legacy mode, we should *not* + // suspend the commit. Pretend as if the suspended component rendered + // null and keep rendering. When the Suspense boundary completes, + // we'll do a second pass to render the fallback. + if (suspenseBoundary === returnFiber) { + // Special case where we suspended while reconciling the children of + // a Suspense boundary's inner Offscreen wrapper fiber. This happens + // when a React.lazy component is a direct child of a + // Suspense boundary. + // + // Suspense boundaries are implemented as multiple fibers, but they + // are a single conceptual unit. The legacy mode behavior where we + // pretend the suspended fiber committed as `null` won't work, + // because in this case the "suspended" fiber is the inner + // Offscreen wrapper. + // + // Because the contents of the boundary haven't started rendering + // yet (i.e. nothing in the tree has partially rendered) we can + // switch to the regular, concurrent mode behavior: mark the + // boundary with ShouldCapture and enter the unwind phase. + suspenseBoundary.flags |= ShouldCapture; + } else { + suspenseBoundary.flags |= DidCapture; + sourceFiber.flags |= ForceUpdateForLegacySuspense; // We're going to commit this fiber even though it didn't complete. + // But we shouldn't call any lifecycle methods or callbacks. Remove + // all lifecycle effect tags. -function rerenderTransition() { - var _rerenderState = rerenderState(), - booleanOrThenable = _rerenderState[0]; - - var hook = updateWorkInProgressHook(); - var start = hook.memoizedState; - var isPending = - typeof booleanOrThenable === "boolean" - ? booleanOrThenable // This will suspend until the async action scope has finished. - : useThenable(booleanOrThenable); - return [isPending, start]; -} + sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete); -function mountId() { - var hook = mountWorkInProgressHook(); - var root = getWorkInProgressRoot(); // TODO: In Fizz, id generation is specific to each server config. Maybe we - // should do this in Fiber, too? Deferring this decision for now because - // there's no other place to store the prefix except for an internal field on - // the public createRoot object, which the fiber tree does not currently have - // a reference to. - - var identifierPrefix = root.identifierPrefix; - var id; - - { - // Use a lowercase r prefix for client-generated ids. - var globalClientId = globalClientIdCounter++; - id = ":" + identifierPrefix + "r" + globalClientId.toString(32) + ":"; - } - - hook.memoizedState = id; - return id; -} + if (sourceFiber.tag === ClassComponent) { + var currentSourceFiber = sourceFiber.alternate; -function updateId() { - var hook = updateWorkInProgressHook(); - var id = hook.memoizedState; - return id; -} + if (currentSourceFiber === null) { + // This is a new mount. Change the tag so it's not mistaken for a + // completed class component. For example, we should not call + // componentWillUnmount if it is deleted. + sourceFiber.tag = IncompleteClassComponent; + } else { + // When we try rendering again, we should not reuse the current fiber, + // since it's known to be in an inconsistent state. Use a force update to + // prevent a bail out. + var update = createUpdate(SyncLane); + update.tag = ForceUpdate; + enqueueUpdate(sourceFiber, update, SyncLane); + } + } // The source fiber did not complete. Mark it with Sync priority to + // indicate that it still has pending work. -function mountRefresh() { - var hook = mountWorkInProgressHook(); - var refresh = (hook.memoizedState = refreshCache.bind( - null, - currentlyRenderingFiber$1 - )); - return refresh; -} + sourceFiber.lanes = mergeLanes(sourceFiber.lanes, SyncLane); + } -function updateRefresh() { - var hook = updateWorkInProgressHook(); - return hook.memoizedState; -} + return suspenseBoundary; + } // Confirmed that the boundary is in a concurrent mode tree. Continue + // with the normal suspend path. + // + // After this we'll use a set of heuristics to determine whether this + // render pass will run to completion or restart or "suspend" the commit. + // The actual logic for this is spread out in different places. + // + // This first principle is that if we're going to suspend when we complete + // a root, then we should also restart if we get an update or ping that + // might unsuspend it, and vice versa. The only reason to suspend is + // because you think you might want to restart before committing. However, + // it doesn't make sense to restart only while in the period we're suspended. + // + // Restarting too aggressively is also not good because it starves out any + // intermediate loading state. So we use heuristics to determine when. + // Suspense Heuristics + // + // If nothing threw a Promise or all the same fallbacks are already showing, + // then don't suspend/restart. + // + // If this is an initial render of a new tree of Suspense boundaries and + // those trigger a fallback, then don't suspend/restart. We want to ensure + // that we can show the initial loading state as quickly as possible. + // + // If we hit a "Delayed" case, such as when we'd switch from content back into + // a fallback, then we should always suspend/restart. Transitions apply + // to this case. If none is defined, JND is used instead. + // + // If we're already showing a fallback and it gets "retried", allowing us to show + // another level, but there's still an inner boundary that would show a fallback, + // then we suspend/restart for 500ms since the last time we showed a fallback + // anywhere in the tree. This effectively throttles progressive loading into a + // consistent train of commits. This also gives us an opportunity to restart to + // get to the completed state slightly earlier. + // + // If there's ambiguity due to batching it's resolved in preference of: + // 1) "delayed", 2) "initial render", 3) "retry". + // + // We want to ensure that a "busy" state doesn't get force committed. We want to + // ensure that new initial loading states can commit as soon as possible. -function refreshCache(fiber, seedKey, seedValue) { - // TODO: Consider warning if the refresh is at discrete priority, or if we - // otherwise suspect that it wasn't batched properly. + suspenseBoundary.flags |= ShouldCapture; // TODO: I think we can remove this, since we now use `DidCapture` in + // the begin phase to prevent an early bailout. - var provider = fiber.return; + suspenseBoundary.lanes = rootRenderLanes; + return suspenseBoundary; + } - while (provider !== null) { - switch (provider.tag) { - case CacheComponent: - case HostRoot: { - // Schedule an update on the cache boundary to trigger a refresh. - var lane = requestUpdateLane(provider); - var refreshUpdate = createUpdate(lane); - var root = enqueueUpdate(provider, refreshUpdate, lane); + function throwException( + root, + returnFiber, + sourceFiber, + value, + rootRenderLanes + ) { + // The source fiber did not complete. + sourceFiber.flags |= Incomplete; - if (root !== null) { - scheduleUpdateOnFiber(root, provider, lane); - entangleTransitions(root, provider, lane); - } // TODO: If a refresh never commits, the new cache created here must be - // released. A simple case is start refreshing a cache boundary, but then - // unmount that boundary before the refresh completes. + { + if (isDevToolsPresent) { + // If we have pending work still, restore the original updaters + restorePendingUpdaters(root, rootRenderLanes); + } + } - var seededCache = createCache(); + if (value !== null && typeof value === "object") { + if (typeof value.then === "function") { + // This is a wakeable. The component suspended. + var wakeable = value; + resetSuspendedComponent(sourceFiber, rootRenderLanes); - if (seedKey !== null && seedKey !== undefined && root !== null) { { - // Seed the cache with the value passed by the caller. This could be - // from a server mutation, or it could be a streaming response. - seededCache.data.set(seedKey, seedValue); - } - } + if (enableDebugTracing) { + if (sourceFiber.mode & DebugTracingMode) { + var name = getComponentNameFromFiber(sourceFiber) || "Unknown"; + logComponentSuspended(name, wakeable); + } + } + } // Mark the nearest Suspense boundary to switch to rendering a fallback. + + var suspenseBoundary = getSuspenseHandler(); + + if (suspenseBoundary !== null) { + switch (suspenseBoundary.tag) { + case SuspenseComponent: { + // If this suspense boundary is not already showing a fallback, mark + // the in-progress render as suspended. We try to perform this logic + // as soon as soon as possible during the render phase, so the work + // loop can know things like whether it's OK to switch to other tasks, + // or whether it can wait for data to resolve before continuing. + // TODO: Most of these checks are already performed when entering a + // Suspense boundary. We should track the information on the stack so + // we don't have to recompute it on demand. This would also allow us + // to unify with `use` which needs to perform this logic even sooner, + // before `throwException` is called. + if (sourceFiber.mode & ConcurrentMode) { + if (getShellBoundary() === null) { + // Suspended in the "shell" of the app. This is an undesirable + // loading state. We should avoid committing this tree. + renderDidSuspendDelayIfPossible(); + } else { + // If we suspended deeper than the shell, we don't need to delay + // the commmit. However, we still call renderDidSuspend if this is + // a new boundary, to tell the work loop that a new fallback has + // appeared during this render. + // TODO: Theoretically we should be able to delete this branch. + // It's currently used for two things: 1) to throttle the + // appearance of successive loading states, and 2) in + // SuspenseList, to determine whether the children include any + // pending fallbacks. For 1, we should apply throttling to all + // retries, not just ones that render an additional fallback. For + // 2, we should check subtreeFlags instead. Then we can delete + // this branch. + var current = suspenseBoundary.alternate; + + if (current === null) { + renderDidSuspend(); + } + } + } - var payload = { - cache: seededCache - }; - refreshUpdate.payload = payload; - return; - } - } + suspenseBoundary.flags &= ~ForceClientRender; + markSuspenseBoundaryShouldCapture( + suspenseBoundary, + returnFiber, + sourceFiber, + root, + rootRenderLanes + ); // Retry listener + // + // If the fallback does commit, we need to attach a different type of + // listener. This one schedules an update on the Suspense boundary to + // turn the fallback state off. + // + // Stash the wakeable on the boundary fiber so we can access it in the + // commit phase. + // + // When the wakeable resolves, we'll attempt to render the boundary + // again ("retry"). + // Check if this is a Suspensey resource. We do not attach retry + // listeners to these, because we don't actually need them for + // rendering. Only for committing. Instead, if a fallback commits + // and the only thing that suspended was a Suspensey resource, we + // retry immediately. + // TODO: Refactor throwException so that we don't have to do this type + // check. The caller already knows what the cause was. + + var isSuspenseyResource = + wakeable === noopSuspenseyCommitThenable; + + if (isSuspenseyResource) { + suspenseBoundary.flags |= ScheduleRetry; + } else { + var retryQueue = suspenseBoundary.updateQueue; - provider = provider.return; - } // TODO: Warn if unmounted? -} + if (retryQueue === null) { + suspenseBoundary.updateQueue = new Set([wakeable]); + } else { + retryQueue.add(wakeable); + } // We only attach ping listeners in concurrent mode. Legacy + // Suspense always commits fallbacks synchronously, so there are + // no pings. -function dispatchReducerAction(fiber, queue, action) { - { - if (typeof arguments[3] === "function") { - 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()." - ); - } - } + if (suspenseBoundary.mode & ConcurrentMode) { + attachPingListener(root, wakeable, rootRenderLanes); + } + } - var lane = requestUpdateLane(fiber); - var update = { - lane: lane, - revertLane: NoLane, - action: action, - hasEagerState: false, - eagerState: null, - next: null - }; + return; + } - if (isRenderPhaseUpdate(fiber)) { - enqueueRenderPhaseUpdate(queue, update); - } else { - var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); + case OffscreenComponent: { + if (suspenseBoundary.mode & ConcurrentMode) { + suspenseBoundary.flags |= ShouldCapture; - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane); - entangleTransitionUpdate(root, queue, lane); - } - } + var _isSuspenseyResource = + wakeable === noopSuspenseyCommitThenable; - markUpdateInDevTools(fiber, lane, action); -} + if (_isSuspenseyResource) { + suspenseBoundary.flags |= ScheduleRetry; + } else { + var offscreenQueue = suspenseBoundary.updateQueue; + + if (offscreenQueue === null) { + var newOffscreenQueue = { + transitions: null, + markerInstances: null, + retryQueue: new Set([wakeable]) + }; + suspenseBoundary.updateQueue = newOffscreenQueue; + } else { + var _retryQueue = offscreenQueue.retryQueue; -function dispatchSetState(fiber, queue, action) { - { - if (typeof arguments[3] === "function") { - 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()." - ); - } - } + if (_retryQueue === null) { + offscreenQueue.retryQueue = new Set([wakeable]); + } else { + _retryQueue.add(wakeable); + } + } - var lane = requestUpdateLane(fiber); - var update = { - lane: lane, - revertLane: NoLane, - action: action, - hasEagerState: false, - eagerState: null, - next: null - }; + attachPingListener(root, wakeable, rootRenderLanes); + } - if (isRenderPhaseUpdate(fiber)) { - enqueueRenderPhaseUpdate(queue, update); - } else { - var alternate = fiber.alternate; + return; + } + } + } - if ( - fiber.lanes === NoLanes && - (alternate === null || alternate.lanes === NoLanes) - ) { - // The queue is currently empty, which means we can eagerly compute the - // next state before entering the render phase. If the new state is the - // same as the current state, we may be able to bail out entirely. - var lastRenderedReducer = queue.lastRenderedReducer; + throw new Error( + "Unexpected Suspense handler tag (" + + suspenseBoundary.tag + + "). This " + + "is a bug in React." + ); + } else { + // No boundary was found. Unless this is a sync update, this is OK. + // We can suspend and wait for more data to arrive. + if (root.tag === ConcurrentRoot) { + // In a concurrent root, suspending without a Suspense boundary is + // allowed. It will suspend indefinitely without committing. + // + // TODO: Should we have different behavior for discrete updates? What + // about flushSync? Maybe it should put the tree into an inert state, + // and potentially log a warning. Revisit this for a future release. + attachPingListener(root, wakeable, rootRenderLanes); + renderDidSuspendDelayIfPossible(); + return; + } else { + // In a legacy root, suspending without a boundary is always an error. + 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." + ); + value = uncaughtSuspenseError; + } + } + } + } // This is a regular error, not a Suspense wakeable. - if (lastRenderedReducer !== null) { - var prevDispatcher; + value = createCapturedValueAtFiber(value, sourceFiber); + renderDidError(value); // We didn't find a boundary that could handle this type of exception. Start + // over and traverse parent path again, this time treating the exception + // as an error. - { - prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; - } + var workInProgress = returnFiber; - try { - var currentState = queue.lastRenderedState; - var eagerState = lastRenderedReducer(currentState, action); // Stash the eagerly computed state, and the reducer used to compute - // it, on the update object. If the reducer hasn't changed by the - // time we enter the render phase, then the eager state can be used - // without calling the reducer again. - - update.hasEagerState = true; - update.eagerState = eagerState; - - if (objectIs(eagerState, currentState)) { - // Fast path. We can bail out without scheduling React to re-render. - // It's still possible that we'll need to rebase this update later, - // if the component re-renders for a different reason and by that - // time the reducer has changed. - // TODO: Do we still need to entangle transitions in this case? - enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update); + do { + switch (workInProgress.tag) { + case HostRoot: { + var _errorInfo = value; + workInProgress.flags |= ShouldCapture; + var lane = pickArbitraryLane(rootRenderLanes); + workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); + var update = createRootErrorUpdate( + workInProgress, + _errorInfo, + lane + ); + enqueueCapturedUpdate(workInProgress, update); return; } - } catch (error) { - // Suppress the error. It will throw again in the render phase. - } finally { - { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - } - } - } - - var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane); - entangleTransitionUpdate(root, queue, lane); - } - } + case ClassComponent: + // Capture and retry + var errorInfo = value; + var ctor = workInProgress.type; + var instance = workInProgress.stateNode; - markUpdateInDevTools(fiber, lane, action); -} + if ( + (workInProgress.flags & DidCapture) === NoFlags$1 && + (typeof ctor.getDerivedStateFromError === "function" || + (instance !== null && + typeof instance.componentDidCatch === "function" && + !isAlreadyFailedLegacyErrorBoundary(instance))) + ) { + workInProgress.flags |= ShouldCapture; -function dispatchOptimisticSetState(fiber, throwIfDuringRender, queue, action) { - { - if (ReactCurrentBatchConfig$2.transition === null) { - // An optimistic update occurred, but startTransition is not on the stack. - // There are two likely scenarios. - // One possibility is that the optimistic update is triggered by a regular - // event handler (e.g. `onSubmit`) instead of an action. This is a mistake - // and we will warn. - // The other possibility is the optimistic update is inside an async - // action, but after an `await`. In this case, we can make it "just work" - // by associating the optimistic update with the pending async action. - // Technically it's possible that the optimistic update is unrelated to - // the pending action, but we don't have a way of knowing this for sure - // because browsers currently do not provide a way to track async scope. - // (The AsyncContext proposal, if it lands, will solve this in the - // future.) However, this is no different than the problem of unrelated - // transitions being grouped together — it's not wrong per se, but it's - // not ideal. - // Once AsyncContext starts landing in browsers, we will provide better - // warnings in development for these cases. - if (peekEntangledActionLane() !== NoLane); - else { - // There's no pending async action. The most likely cause is that we're - // inside a regular event handler (e.g. onSubmit) instead of an action. - error( - "An optimistic state update occurred outside a transition or " + - "action. To fix, move the update to an action, or wrap " + - "with startTransition." - ); - } - } - } - - var update = { - // An optimistic update commits synchronously. - lane: SyncLane, - // After committing, the optimistic update is "reverted" using the same - // lane as the transition it's associated with. - revertLane: requestTransitionLane(), - action: action, - hasEagerState: false, - eagerState: null, - next: null - }; - - if (isRenderPhaseUpdate(fiber)) { - // When calling startTransition during render, this warns instead of - // throwing because throwing would be a breaking change. setOptimisticState - // is a new API so it's OK to throw. - if (throwIfDuringRender) { - throw new Error("Cannot update optimistic state while rendering."); - } else { - // startTransition was called during render. We don't need to do anything - // besides warn here because the render phase update would be overidden by - // the second update, anyway. We can remove this branch and make it throw - // in a future release. - { - error("Cannot call startTransition while rendering."); - } - } - } else { - var root = enqueueConcurrentHookUpdate(fiber, queue, update, SyncLane); + var _lane = pickArbitraryLane(rootRenderLanes); - if (root !== null) { - // NOTE: The optimistic update implementation assumes that the transition - // will never be attempted before the optimistic update. This currently - // holds because the optimistic update is always synchronous. If we ever - // change that, we'll need to account for this. - scheduleUpdateOnFiber(root, fiber, SyncLane); // Optimistic updates are always synchronous, so we don't need to call - // entangleTransitionUpdate here. - } - } + workInProgress.lanes = mergeLanes(workInProgress.lanes, _lane); // Schedule the error boundary to re-render using updated state - markUpdateInDevTools(fiber, SyncLane, action); -} + var _update = createClassErrorUpdate( + workInProgress, + errorInfo, + _lane + ); -function isRenderPhaseUpdate(fiber) { - var alternate = fiber.alternate; - return ( - fiber === currentlyRenderingFiber$1 || - (alternate !== null && alternate === currentlyRenderingFiber$1) - ); -} + enqueueCapturedUpdate(workInProgress, _update); + return; + } -function enqueueRenderPhaseUpdate(queue, update) { - // This is a render phase update. Stash it in a lazily-created map of - // queue -> linked list of updates. After this render pass, we'll restart - // and apply the stashed updates on top of the work-in-progress hook. - didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = - true; - var pending = queue.pending; - - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; - } - - queue.pending = update; -} // TODO: Move to ReactFiberConcurrentUpdates? - -function entangleTransitionUpdate(root, queue, lane) { - if (isTransitionLane(lane)) { - var queueLanes = queue.lanes; // If any entangled lanes are no longer pending on the root, then they - // must have finished. We can remove them from the shared queue, which - // represents a superset of the actually pending lanes. In some cases we - // may entangle more than we need to, but that's OK. In fact it's worse if - // we *don't* entangle when we should. - - queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. - - var newQueueLanes = mergeLanes(queueLanes, lane); - queue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if - // the lane finished since the last time we entangled it. So we need to - // entangle it again, just to be sure. - - markRootEntangled(root, newQueueLanes); - } -} + break; + } // $FlowFixMe[incompatible-type] we bail out when we get a null -function markUpdateInDevTools(fiber, lane, action) { - { - if (enableDebugTracing) { - if (fiber.mode & DebugTracingMode) { - var name = getComponentNameFromFiber(fiber) || "Unknown"; - logStateUpdateScheduled(name, lane, action); - } + workInProgress = workInProgress.return; + } while (workInProgress !== null); } - } - if (enableSchedulingProfiler) { - markStateUpdateScheduled(fiber, lane); - } -} - -var ContextOnlyDispatcher = { - readContext: readContext, - use: use, - useCallback: throwInvalidHookError, - useContext: throwInvalidHookError, - useEffect: throwInvalidHookError, - useImperativeHandle: throwInvalidHookError, - useInsertionEffect: throwInvalidHookError, - useLayoutEffect: throwInvalidHookError, - useMemo: throwInvalidHookError, - useReducer: throwInvalidHookError, - useRef: throwInvalidHookError, - useState: throwInvalidHookError, - useDebugValue: throwInvalidHookError, - useDeferredValue: throwInvalidHookError, - useTransition: throwInvalidHookError, - useSyncExternalStore: throwInvalidHookError, - useId: throwInvalidHookError -}; - -{ - ContextOnlyDispatcher.useCacheRefresh = throwInvalidHookError; -} + var TransitionRoot = 0; + var TransitionTracingMarker = 1; + function processTransitionCallbacks( + pendingTransitions, + endTime, + callbacks + ) { + if (enableTransitionTracing) { + if (pendingTransitions !== null) { + var transitionStart = pendingTransitions.transitionStart; + var onTransitionStart = callbacks.onTransitionStart; -{ - ContextOnlyDispatcher.useMemoCache = throwInvalidHookError; -} + if (transitionStart !== null && onTransitionStart != null) { + transitionStart.forEach(function (transition) { + return onTransitionStart(transition.name, transition.startTime); + }); + } -{ - ContextOnlyDispatcher.useEffectEvent = throwInvalidHookError; -} + var markerProgress = pendingTransitions.markerProgress; + var onMarkerProgress = callbacks.onMarkerProgress; + + if (onMarkerProgress != null && markerProgress !== null) { + markerProgress.forEach(function (markerInstance, markerName) { + if (markerInstance.transitions !== null) { + // TODO: Clone the suspense object so users can't modify it + var pending = + markerInstance.pendingBoundaries !== null + ? Array.from(markerInstance.pendingBoundaries.values()) + : []; + markerInstance.transitions.forEach(function (transition) { + onMarkerProgress( + transition.name, + markerName, + transition.startTime, + endTime, + pending + ); + }); + } + }); + } -if (enableAsyncActions) { - ContextOnlyDispatcher.useOptimistic = throwInvalidHookError; -} + var markerComplete = pendingTransitions.markerComplete; + var onMarkerComplete = callbacks.onMarkerComplete; -var HooksDispatcherOnMountInDEV = null; -var HooksDispatcherOnMountWithHookTypesInDEV = null; -var HooksDispatcherOnUpdateInDEV = null; -var HooksDispatcherOnRerenderInDEV = null; -var InvalidNestedHooksDispatcherOnMountInDEV = null; -var InvalidNestedHooksDispatcherOnUpdateInDEV = null; -var InvalidNestedHooksDispatcherOnRerenderInDEV = null; - -{ - var warnInvalidContextAccess = function () { - 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()." - ); - }; - - var warnInvalidHookAccess = function () { - 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" - ); - }; - - HooksDispatcherOnMountInDEV = { - readContext: function (context) { - return readContext(context); - }, - use: use, - useCallback: function (callback, deps) { - currentHookNameInDev = "useCallback"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - return mountCallback(callback, deps); - }, - useContext: function (context) { - currentHookNameInDev = "useContext"; - mountHookTypesDev(); - return readContext(context); - }, - useEffect: function (create, deps) { - currentHookNameInDev = "useEffect"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - return mountEffect(create, deps); - }, - useImperativeHandle: function (ref, create, deps) { - currentHookNameInDev = "useImperativeHandle"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - return mountImperativeHandle(ref, create, deps); - }, - useInsertionEffect: function (create, deps) { - currentHookNameInDev = "useInsertionEffect"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - return mountInsertionEffect(create, deps); - }, - useLayoutEffect: function (create, deps) { - currentHookNameInDev = "useLayoutEffect"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - return mountLayoutEffect(create, deps); - }, - useMemo: function (create, deps) { - currentHookNameInDev = "useMemo"; - mountHookTypesDev(); - checkDepsAreArrayDev(deps); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + if (markerComplete !== null && onMarkerComplete != null) { + markerComplete.forEach(function (transitions, markerName) { + transitions.forEach(function (transition) { + onMarkerComplete( + transition.name, + markerName, + transition.startTime, + endTime + ); + }); + }); + } - try { - return mountMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useReducer: function (reducer, initialArg, init) { - currentHookNameInDev = "useReducer"; - mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + var markerIncomplete = pendingTransitions.markerIncomplete; + var onMarkerIncomplete = callbacks.onMarkerIncomplete; + + if (onMarkerIncomplete != null && markerIncomplete !== null) { + markerIncomplete.forEach(function (_ref, markerName) { + var transitions = _ref.transitions, + aborts = _ref.aborts; + transitions.forEach(function (transition) { + var filteredAborts = []; + aborts.forEach(function (abort) { + switch (abort.reason) { + case "marker": { + filteredAborts.push({ + type: "marker", + name: abort.name, + endTime: endTime + }); + break; + } - try { - return mountReducer(reducer, initialArg, init); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useRef: function (initialValue) { - currentHookNameInDev = "useRef"; - mountHookTypesDev(); - return mountRef(initialValue); - }, - useState: function (initialState) { - currentHookNameInDev = "useState"; - mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + case "suspense": { + filteredAborts.push({ + type: "suspense", + name: abort.name, + endTime: endTime + }); + break; + } + } + }); - try { - return mountState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function (value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - mountHookTypesDev(); - return mountDebugValue(); - }, - useDeferredValue: function (value, initialValue) { - currentHookNameInDev = "useDeferredValue"; - mountHookTypesDev(); - return mountDeferredValue(value, initialValue); - }, - useTransition: function () { - currentHookNameInDev = "useTransition"; - mountHookTypesDev(); - return mountTransition(); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - mountHookTypesDev(); - return mountSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - mountHookTypesDev(); - return mountId(); - } - }; - - { - HooksDispatcherOnMountInDEV.useCacheRefresh = function useCacheRefresh() { - currentHookNameInDev = "useCacheRefresh"; - mountHookTypesDev(); - return mountRefresh(); - }; - } + if (filteredAborts.length > 0) { + onMarkerIncomplete( + transition.name, + markerName, + transition.startTime, + filteredAborts + ); + } + }); + }); + } - { - HooksDispatcherOnMountInDEV.useMemoCache = useMemoCache; - } + var transitionProgress = pendingTransitions.transitionProgress; + var onTransitionProgress = callbacks.onTransitionProgress; - { - HooksDispatcherOnMountInDEV.useEffectEvent = function useEffectEvent( - callback - ) { - currentHookNameInDev = "useEffectEvent"; - mountHookTypesDev(); - return mountEvent(callback); - }; - } + if (onTransitionProgress != null && transitionProgress !== null) { + transitionProgress.forEach(function (pending, transition) { + onTransitionProgress( + transition.name, + transition.startTime, + endTime, + Array.from(pending.values()) + ); + }); + } - if (enableAsyncActions) { - HooksDispatcherOnMountInDEV.useOptimistic = function useOptimistic( - passthrough, - reducer - ) { - currentHookNameInDev = "useOptimistic"; - mountHookTypesDev(); - return mountOptimistic(passthrough); - }; - } - - HooksDispatcherOnMountWithHookTypesInDEV = { - readContext: function (context) { - return readContext(context); - }, - use: use, - useCallback: function (callback, deps) { - currentHookNameInDev = "useCallback"; - updateHookTypesDev(); - return mountCallback(callback, deps); - }, - useContext: function (context) { - currentHookNameInDev = "useContext"; - updateHookTypesDev(); - return readContext(context); - }, - useEffect: function (create, deps) { - currentHookNameInDev = "useEffect"; - updateHookTypesDev(); - return mountEffect(create, deps); - }, - useImperativeHandle: function (ref, create, deps) { - currentHookNameInDev = "useImperativeHandle"; - updateHookTypesDev(); - return mountImperativeHandle(ref, create, deps); - }, - useInsertionEffect: function (create, deps) { - currentHookNameInDev = "useInsertionEffect"; - updateHookTypesDev(); - return mountInsertionEffect(create, deps); - }, - useLayoutEffect: function (create, deps) { - currentHookNameInDev = "useLayoutEffect"; - updateHookTypesDev(); - return mountLayoutEffect(create, deps); - }, - useMemo: function (create, deps) { - currentHookNameInDev = "useMemo"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + var transitionComplete = pendingTransitions.transitionComplete; + var onTransitionComplete = callbacks.onTransitionComplete; - try { - return mountMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + if (transitionComplete !== null && onTransitionComplete != null) { + transitionComplete.forEach(function (transition) { + return onTransitionComplete( + transition.name, + transition.startTime, + endTime + ); + }); + } + } } - }, - useReducer: function (reducer, initialArg, init) { - currentHookNameInDev = "useReducer"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + } // For every tracing marker, store a pointer to it. We will later access it + // to get the set of suspense boundaries that need to resolve before the + // tracing marker can be logged as complete + // This code lives separate from the ReactFiberTransition code because + // we push and pop on the tracing marker, not the suspense boundary - try { - return mountReducer(reducer, initialArg, init); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useRef: function (initialValue) { - currentHookNameInDev = "useRef"; - updateHookTypesDev(); - return mountRef(initialValue); - }, - useState: function (initialState) { - currentHookNameInDev = "useState"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + var markerInstanceStack = createCursor(null); + function pushRootMarkerInstance(workInProgress) { + if (enableTransitionTracing) { + // On the root, every transition gets mapped to it's own map of + // suspense boundaries. The transition is marked as complete when + // the suspense boundaries map is empty. We do this because every + // transition completes at different times and depends on different + // suspense boundaries to complete. We store all the transitions + // along with its map of suspense boundaries in the root incomplete + // transitions map. Each entry in this map functions like a tracing + // marker does, so we can push it onto the marker instance stack + var transitions = getWorkInProgressTransitions(); + var root = workInProgress.stateNode; - try { - return mountState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function (value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - updateHookTypesDev(); - return mountDebugValue(); - }, - useDeferredValue: function (value, initialValue) { - currentHookNameInDev = "useDeferredValue"; - updateHookTypesDev(); - return mountDeferredValue(value, initialValue); - }, - useTransition: function () { - currentHookNameInDev = "useTransition"; - updateHookTypesDev(); - return mountTransition(); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - updateHookTypesDev(); - return mountSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - updateHookTypesDev(); - return mountId(); - } - }; - - { - HooksDispatcherOnMountWithHookTypesInDEV.useCacheRefresh = - function useCacheRefresh() { - currentHookNameInDev = "useCacheRefresh"; - updateHookTypesDev(); - return mountRefresh(); - }; - } - - { - HooksDispatcherOnMountWithHookTypesInDEV.useMemoCache = useMemoCache; - } - - { - HooksDispatcherOnMountWithHookTypesInDEV.useEffectEvent = - function useEffectEvent(callback) { - currentHookNameInDev = "useEffectEvent"; - updateHookTypesDev(); - return mountEvent(callback); - }; - } - - if (enableAsyncActions) { - HooksDispatcherOnMountWithHookTypesInDEV.useOptimistic = - function useOptimistic(passthrough, reducer) { - currentHookNameInDev = "useOptimistic"; - updateHookTypesDev(); - return mountOptimistic(passthrough); - }; - } - - HooksDispatcherOnUpdateInDEV = { - readContext: function (context) { - return readContext(context); - }, - use: use, - useCallback: function (callback, deps) { - currentHookNameInDev = "useCallback"; - updateHookTypesDev(); - return updateCallback(callback, deps); - }, - useContext: function (context) { - currentHookNameInDev = "useContext"; - updateHookTypesDev(); - return readContext(context); - }, - useEffect: function (create, deps) { - currentHookNameInDev = "useEffect"; - updateHookTypesDev(); - return updateEffect(create, deps); - }, - useImperativeHandle: function (ref, create, deps) { - currentHookNameInDev = "useImperativeHandle"; - updateHookTypesDev(); - return updateImperativeHandle(ref, create, deps); - }, - useInsertionEffect: function (create, deps) { - currentHookNameInDev = "useInsertionEffect"; - updateHookTypesDev(); - return updateInsertionEffect(create, deps); - }, - useLayoutEffect: function (create, deps) { - currentHookNameInDev = "useLayoutEffect"; - updateHookTypesDev(); - return updateLayoutEffect(create, deps); - }, - useMemo: function (create, deps) { - currentHookNameInDev = "useMemo"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + if (transitions !== null) { + transitions.forEach(function (transition) { + if (!root.incompleteTransitions.has(transition)) { + var markerInstance = { + tag: TransitionRoot, + transitions: new Set([transition]), + pendingBoundaries: null, + aborts: null, + name: null + }; + root.incompleteTransitions.set(transition, markerInstance); + } + }); + } - try { - return updateMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + var markerInstances = []; // For ever transition on the suspense boundary, we push the transition + // along with its map of pending suspense boundaries onto the marker + // instance stack. + + root.incompleteTransitions.forEach(function (markerInstance) { + markerInstances.push(markerInstance); + }); + push(markerInstanceStack, markerInstances, workInProgress); + } + } + function popRootMarkerInstance(workInProgress) { + if (enableTransitionTracing) { + pop(markerInstanceStack, workInProgress); + } + } + function pushMarkerInstance(workInProgress, markerInstance) { + if (enableTransitionTracing) { + if (markerInstanceStack.current === null) { + push(markerInstanceStack, [markerInstance], workInProgress); + } else { + push( + markerInstanceStack, + markerInstanceStack.current.concat(markerInstance), + workInProgress + ); + } + } + } + function popMarkerInstance(workInProgress) { + if (enableTransitionTracing) { + pop(markerInstanceStack, workInProgress); + } + } + function getMarkerInstances() { + if (enableTransitionTracing) { + return markerInstanceStack.current; } - }, - useReducer: function (reducer, initialArg, init) { - currentHookNameInDev = "useReducer"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; - try { - return updateReducer(reducer, initialArg, init); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useRef: function (initialValue) { - currentHookNameInDev = "useRef"; - updateHookTypesDev(); - return updateRef(); - }, - useState: function (initialState) { - currentHookNameInDev = "useState"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + return null; + } - try { - return updateState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function (value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - updateHookTypesDev(); - return updateDebugValue(); - }, - useDeferredValue: function (value, initialValue) { - currentHookNameInDev = "useDeferredValue"; - updateHookTypesDev(); - return updateDeferredValue(value, initialValue); - }, - useTransition: function () { - currentHookNameInDev = "useTransition"; - updateHookTypesDev(); - return updateTransition(); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - updateHookTypesDev(); - return updateId(); - } - }; - - { - HooksDispatcherOnUpdateInDEV.useCacheRefresh = function useCacheRefresh() { - currentHookNameInDev = "useCacheRefresh"; - updateHookTypesDev(); - return updateRefresh(); - }; - } + var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; // A special exception that's used to unwind the stack when an update flows + // into a dehydrated boundary. + + var SelectiveHydrationException = new Error( + "This is not a real error. It's an implementation detail of React's " + + "selective hydration feature. If this leaks into userspace, it's a bug in " + + "React. Please file an issue." + ); + var didReceiveUpdate = false; + var didWarnAboutBadClass; + var didWarnAboutModulePatternComponent; + var didWarnAboutContextTypeOnFunctionComponent; + var didWarnAboutGetDerivedStateOnFunctionComponent; + var didWarnAboutFunctionRefs; + var didWarnAboutReassigningProps; + var didWarnAboutRevealOrder; + var didWarnAboutTailOptions; + var didWarnAboutDefaultPropsOnFunctionComponent; - { - HooksDispatcherOnUpdateInDEV.useMemoCache = useMemoCache; - } + { + didWarnAboutBadClass = {}; + didWarnAboutModulePatternComponent = {}; + didWarnAboutContextTypeOnFunctionComponent = {}; + didWarnAboutGetDerivedStateOnFunctionComponent = {}; + didWarnAboutFunctionRefs = {}; + didWarnAboutReassigningProps = false; + didWarnAboutRevealOrder = {}; + didWarnAboutTailOptions = {}; + didWarnAboutDefaultPropsOnFunctionComponent = {}; + } + + function reconcileChildren( + current, + workInProgress, + nextChildren, + renderLanes + ) { + if (current === null) { + // If this is a fresh new component that hasn't been rendered yet, we + // won't update its child set by applying minimal side-effects. Instead, + // we will add them all to the child before it gets rendered. That means + // we can optimize this reconciliation pass by not tracking side-effects. + workInProgress.child = mountChildFibers( + workInProgress, + null, + nextChildren, + renderLanes + ); + } else { + // If the current child is the same as the work in progress, it means that + // we haven't yet started any work on these children. Therefore, we use + // the clone algorithm to create a copy of all the current children. + // If we had any progressed work already, that is invalid at this point so + // let's throw it out. + workInProgress.child = reconcileChildFibers( + workInProgress, + current.child, + nextChildren, + renderLanes + ); + } + } - { - HooksDispatcherOnUpdateInDEV.useEffectEvent = function useEffectEvent( - callback + function forceUnmountCurrentAndReconcile( + current, + workInProgress, + nextChildren, + renderLanes ) { - currentHookNameInDev = "useEffectEvent"; - updateHookTypesDev(); - return updateEvent(callback); - }; - } + // This function is fork of reconcileChildren. It's used in cases where we + // want to reconcile without matching against the existing set. This has the + // effect of all current children being unmounted; even if the type and key + // are the same, the old child is unmounted and a new child is created. + // + // To do this, we're going to go through the reconcile algorithm twice. In + // the first pass, we schedule a deletion for all the current children by + // passing null. + workInProgress.child = reconcileChildFibers( + workInProgress, + current.child, + null, + renderLanes + ); // In the second pass, we mount the new children. The trick here is that we + // pass null in place of where we usually pass the current child set. This has + // the effect of remounting all children regardless of whether their + // identities match. + + workInProgress.child = reconcileChildFibers( + workInProgress, + null, + nextChildren, + renderLanes + ); + } - if (enableAsyncActions) { - HooksDispatcherOnUpdateInDEV.useOptimistic = function useOptimistic( - passthrough, - reducer + function updateForwardRef( + current, + workInProgress, + Component, + nextProps, + renderLanes ) { - currentHookNameInDev = "useOptimistic"; - updateHookTypesDev(); - return updateOptimistic(passthrough, reducer); - }; - } - - HooksDispatcherOnRerenderInDEV = { - readContext: function (context) { - return readContext(context); - }, - use: use, - useCallback: function (callback, deps) { - currentHookNameInDev = "useCallback"; - updateHookTypesDev(); - return updateCallback(callback, deps); - }, - useContext: function (context) { - currentHookNameInDev = "useContext"; - updateHookTypesDev(); - return readContext(context); - }, - useEffect: function (create, deps) { - currentHookNameInDev = "useEffect"; - updateHookTypesDev(); - return updateEffect(create, deps); - }, - useImperativeHandle: function (ref, create, deps) { - currentHookNameInDev = "useImperativeHandle"; - updateHookTypesDev(); - return updateImperativeHandle(ref, create, deps); - }, - useInsertionEffect: function (create, deps) { - currentHookNameInDev = "useInsertionEffect"; - updateHookTypesDev(); - return updateInsertionEffect(create, deps); - }, - useLayoutEffect: function (create, deps) { - currentHookNameInDev = "useLayoutEffect"; - updateHookTypesDev(); - return updateLayoutEffect(create, deps); - }, - useMemo: function (create, deps) { - currentHookNameInDev = "useMemo"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnRerenderInDEV; + // TODO: current can be non-null here even if the component + // hasn't yet mounted. This happens after the first render suspends. + // We'll need to figure out if this is fine or can cause issues. + { + if (workInProgress.type !== workInProgress.elementType) { + // Lazy component props can't be validated in createElement + // because they're only guaranteed to be resolved here. + var innerPropTypes = Component.propTypes; - try { - return updateMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + if (innerPropTypes) { + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(Component) + ); + } + } } - }, - useReducer: function (reducer, initialArg, init) { - currentHookNameInDev = "useReducer"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnRerenderInDEV; - - try { - return rerenderReducer(reducer, initialArg, init); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useRef: function (initialValue) { - currentHookNameInDev = "useRef"; - updateHookTypesDev(); - return updateRef(); - }, - useState: function (initialState) { - currentHookNameInDev = "useState"; - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnRerenderInDEV; - - try { - return rerenderState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function (value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - updateHookTypesDev(); - return updateDebugValue(); - }, - useDeferredValue: function (value, initialValue) { - currentHookNameInDev = "useDeferredValue"; - updateHookTypesDev(); - return rerenderDeferredValue(value, initialValue); - }, - useTransition: function () { - currentHookNameInDev = "useTransition"; - updateHookTypesDev(); - return rerenderTransition(); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - updateHookTypesDev(); - return updateId(); - } - }; - - { - HooksDispatcherOnRerenderInDEV.useCacheRefresh = - function useCacheRefresh() { - currentHookNameInDev = "useCacheRefresh"; - updateHookTypesDev(); - return updateRefresh(); - }; - } - { - HooksDispatcherOnRerenderInDEV.useMemoCache = useMemoCache; - } + var render = Component.render; + var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent - { - HooksDispatcherOnRerenderInDEV.useEffectEvent = function useEffectEvent( - callback - ) { - currentHookNameInDev = "useEffectEvent"; - updateHookTypesDev(); - return updateEvent(callback); - }; - } - - if (enableAsyncActions) { - HooksDispatcherOnRerenderInDEV.useOptimistic = function useOptimistic( - passthrough, - reducer - ) { - currentHookNameInDev = "useOptimistic"; - updateHookTypesDev(); - return rerenderOptimistic(passthrough, reducer); - }; - } - - InvalidNestedHooksDispatcherOnMountInDEV = { - readContext: function (context) { - warnInvalidContextAccess(); - return readContext(context); - }, - use: function (usable) { - warnInvalidHookAccess(); - return use(usable); - }, - useCallback: function (callback, deps) { - currentHookNameInDev = "useCallback"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountCallback(callback, deps); - }, - useContext: function (context) { - currentHookNameInDev = "useContext"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return readContext(context); - }, - useEffect: function (create, deps) { - currentHookNameInDev = "useEffect"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountEffect(create, deps); - }, - useImperativeHandle: function (ref, create, deps) { - currentHookNameInDev = "useImperativeHandle"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountImperativeHandle(ref, create, deps); - }, - useInsertionEffect: function (create, deps) { - currentHookNameInDev = "useInsertionEffect"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountInsertionEffect(create, deps); - }, - useLayoutEffect: function (create, deps) { - currentHookNameInDev = "useLayoutEffect"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountLayoutEffect(create, deps); - }, - useMemo: function (create, deps) { - currentHookNameInDev = "useMemo"; - warnInvalidHookAccess(); - mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; + var nextChildren; + prepareToReadContext(workInProgress, renderLanes); - try { - return mountMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + if (enableSchedulingProfiler) { + markComponentRenderStarted(workInProgress); } - }, - useReducer: function (reducer, initialArg, init) { - currentHookNameInDev = "useReducer"; - warnInvalidHookAccess(); - mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; - - try { - return mountReducer(reducer, initialArg, init); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useRef: function (initialValue) { - currentHookNameInDev = "useRef"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountRef(initialValue); - }, - useState: function (initialState) { - currentHookNameInDev = "useState"; - warnInvalidHookAccess(); - mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnMountInDEV; - try { - return mountState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function (value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountDebugValue(); - }, - useDeferredValue: function (value, initialValue) { - currentHookNameInDev = "useDeferredValue"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountDeferredValue(value, initialValue); - }, - useTransition: function () { - currentHookNameInDev = "useTransition"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountTransition(); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountId(); - } - }; - - { - InvalidNestedHooksDispatcherOnMountInDEV.useCacheRefresh = - function useCacheRefresh() { - currentHookNameInDev = "useCacheRefresh"; - mountHookTypesDev(); - return mountRefresh(); - }; - } + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + nextChildren = renderWithHooks( + current, + workInProgress, + render, + nextProps, + ref, + renderLanes + ); + setIsRendering(false); + } - { - InvalidNestedHooksDispatcherOnMountInDEV.useMemoCache = function (size) { - warnInvalidHookAccess(); - return useMemoCache(size); - }; - } - - { - InvalidNestedHooksDispatcherOnMountInDEV.useEffectEvent = - function useEffectEvent(callback) { - currentHookNameInDev = "useEffectEvent"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountEvent(callback); - }; - } - - if (enableAsyncActions) { - InvalidNestedHooksDispatcherOnMountInDEV.useOptimistic = - function useOptimistic(passthrough, reducer) { - currentHookNameInDev = "useOptimistic"; - warnInvalidHookAccess(); - mountHookTypesDev(); - return mountOptimistic(passthrough); - }; - } - - InvalidNestedHooksDispatcherOnUpdateInDEV = { - readContext: function (context) { - warnInvalidContextAccess(); - return readContext(context); - }, - use: function (usable) { - warnInvalidHookAccess(); - return use(usable); - }, - useCallback: function (callback, deps) { - currentHookNameInDev = "useCallback"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateCallback(callback, deps); - }, - useContext: function (context) { - currentHookNameInDev = "useContext"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return readContext(context); - }, - useEffect: function (create, deps) { - currentHookNameInDev = "useEffect"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateEffect(create, deps); - }, - useImperativeHandle: function (ref, create, deps) { - currentHookNameInDev = "useImperativeHandle"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateImperativeHandle(ref, create, deps); - }, - useInsertionEffect: function (create, deps) { - currentHookNameInDev = "useInsertionEffect"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateInsertionEffect(create, deps); - }, - useLayoutEffect: function (create, deps) { - currentHookNameInDev = "useLayoutEffect"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateLayoutEffect(create, deps); - }, - useMemo: function (create, deps) { - currentHookNameInDev = "useMemo"; - warnInvalidHookAccess(); - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + if (enableSchedulingProfiler) { + markComponentRenderStopped(); + } - try { - return updateMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; + if (current !== null && !didReceiveUpdate) { + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); } - }, - useReducer: function (reducer, initialArg, init) { - currentHookNameInDev = "useReducer"; - warnInvalidHookAccess(); - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; - try { - return updateReducer(reducer, initialArg, init); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useRef: function (initialValue) { - currentHookNameInDev = "useRef"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateRef(); - }, - useState: function (initialState) { - currentHookNameInDev = "useState"; - warnInvalidHookAccess(); - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } - try { - return updateState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function (value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateDebugValue(); - }, - useDeferredValue: function (value, initialValue) { - currentHookNameInDev = "useDeferredValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateDeferredValue(value, initialValue); - }, - useTransition: function () { - currentHookNameInDev = "useTransition"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateTransition(); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateId(); - } - }; - - { - InvalidNestedHooksDispatcherOnUpdateInDEV.useCacheRefresh = - function useCacheRefresh() { - currentHookNameInDev = "useCacheRefresh"; - updateHookTypesDev(); - return updateRefresh(); - }; - } + function updateMemoComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ) { + if (current === null) { + var type = Component.type; - { - InvalidNestedHooksDispatcherOnUpdateInDEV.useMemoCache = function (size) { - warnInvalidHookAccess(); - return useMemoCache(size); - }; - } - - { - InvalidNestedHooksDispatcherOnUpdateInDEV.useEffectEvent = - function useEffectEvent(callback) { - currentHookNameInDev = "useEffectEvent"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateEvent(callback); - }; - } - - if (enableAsyncActions) { - InvalidNestedHooksDispatcherOnUpdateInDEV.useOptimistic = - function useOptimistic(passthrough, reducer) { - currentHookNameInDev = "useOptimistic"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateOptimistic(passthrough, reducer); - }; - } - - InvalidNestedHooksDispatcherOnRerenderInDEV = { - readContext: function (context) { - warnInvalidContextAccess(); - return readContext(context); - }, - use: function (usable) { - warnInvalidHookAccess(); - return use(usable); - }, - useCallback: function (callback, deps) { - currentHookNameInDev = "useCallback"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateCallback(callback, deps); - }, - useContext: function (context) { - currentHookNameInDev = "useContext"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return readContext(context); - }, - useEffect: function (create, deps) { - currentHookNameInDev = "useEffect"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateEffect(create, deps); - }, - useImperativeHandle: function (ref, create, deps) { - currentHookNameInDev = "useImperativeHandle"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateImperativeHandle(ref, create, deps); - }, - useInsertionEffect: function (create, deps) { - currentHookNameInDev = "useInsertionEffect"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateInsertionEffect(create, deps); - }, - useLayoutEffect: function (create, deps) { - currentHookNameInDev = "useLayoutEffect"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateLayoutEffect(create, deps); - }, - useMemo: function (create, deps) { - currentHookNameInDev = "useMemo"; - warnInvalidHookAccess(); - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + if ( + isSimpleFunctionComponent(type) && + Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. + Component.defaultProps === undefined + ) { + var resolvedType = type; - try { - return updateMemo(create, deps); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useReducer: function (reducer, initialArg, init) { - currentHookNameInDev = "useReducer"; - warnInvalidHookAccess(); - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + { + resolvedType = resolveFunctionForHotReloading(type); + } // If this is a plain function component without default props, + // and with only the default shallow comparison, we upgrade it + // to a SimpleMemoComponent to allow fast path updates. - try { - return rerenderReducer(reducer, initialArg, init); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useRef: function (initialValue) { - currentHookNameInDev = "useRef"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateRef(); - }, - useState: function (initialState) { - currentHookNameInDev = "useState"; - warnInvalidHookAccess(); - updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + workInProgress.tag = SimpleMemoComponent; + workInProgress.type = resolvedType; - try { - return rerenderState(initialState); - } finally { - ReactCurrentDispatcher$1.current = prevDispatcher; - } - }, - useDebugValue: function (value, formatterFn) { - currentHookNameInDev = "useDebugValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateDebugValue(); - }, - useDeferredValue: function (value, initialValue) { - currentHookNameInDev = "useDeferredValue"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return rerenderDeferredValue(value, initialValue); - }, - useTransition: function () { - currentHookNameInDev = "useTransition"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return rerenderTransition(); - }, - useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { - currentHookNameInDev = "useSyncExternalStore"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateSyncExternalStore(subscribe, getSnapshot); - }, - useId: function () { - currentHookNameInDev = "useId"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateId(); - } - }; - - { - InvalidNestedHooksDispatcherOnRerenderInDEV.useCacheRefresh = - function useCacheRefresh() { - currentHookNameInDev = "useCacheRefresh"; - updateHookTypesDev(); - return updateRefresh(); - }; - } + { + validateFunctionComponentInDev(workInProgress, type); + } - { - InvalidNestedHooksDispatcherOnRerenderInDEV.useMemoCache = function (size) { - warnInvalidHookAccess(); - return useMemoCache(size); - }; - } - - { - InvalidNestedHooksDispatcherOnRerenderInDEV.useEffectEvent = - function useEffectEvent(callback) { - currentHookNameInDev = "useEffectEvent"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return updateEvent(callback); - }; - } - - if (enableAsyncActions) { - InvalidNestedHooksDispatcherOnRerenderInDEV.useOptimistic = - function useOptimistic(passthrough, reducer) { - currentHookNameInDev = "useOptimistic"; - warnInvalidHookAccess(); - updateHookTypesDev(); - return rerenderOptimistic(passthrough, reducer); - }; - } -} + return updateSimpleMemoComponent( + current, + workInProgress, + resolvedType, + nextProps, + renderLanes + ); + } -var now = Scheduler.unstable_now; -var commitTime = 0; -var layoutEffectStartTime = -1; -var profilerStartTime = -1; -var passiveEffectStartTime = -1; -/** - * Tracks whether the current update was a nested/cascading update (scheduled from a layout effect). - * - * The overall sequence is: - * 1. render - * 2. commit (and call `onRender`, `onCommit`) - * 3. check for nested updates - * 4. flush passive effects (and call `onPostCommit`) - * - * Nested updates are identified in step 3 above, - * but step 4 still applies to the work that was just committed. - * We use two flags to track nested updates then: - * one tracks whether the upcoming update is a nested update, - * and the other tracks whether the current update was a nested update. - * The first value gets synced to the second at the start of the render phase. - */ + { + var innerPropTypes = type.propTypes; -var currentUpdateIsNested = false; -var nestedUpdateScheduled = false; + if (innerPropTypes) { + // Inner memo component props aren't currently validated in createElement. + // We could move it there, but we'd still need this for lazy code path. + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(type) + ); + } -function isCurrentUpdateNested() { - return currentUpdateIsNested; -} + if (Component.defaultProps !== undefined) { + var componentName = getComponentNameFromType(type) || "Unknown"; -function markNestedUpdateScheduled() { - { - nestedUpdateScheduled = true; - } -} + if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) { + error( + "%s: Support for defaultProps will be removed from memo components " + + "in a future major release. Use JavaScript default parameters instead.", + componentName + ); -function resetNestedUpdateFlag() { - { - currentUpdateIsNested = false; - nestedUpdateScheduled = false; - } -} + didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true; + } + } + } -function syncNestedUpdateFlag() { - { - currentUpdateIsNested = nestedUpdateScheduled; - nestedUpdateScheduled = false; - } -} + var child = createFiberFromTypeAndProps( + Component.type, + null, + nextProps, + null, + workInProgress, + workInProgress.mode, + renderLanes + ); + child.ref = workInProgress.ref; + child.return = workInProgress; + workInProgress.child = child; + return child; + } -function getCommitTime() { - return commitTime; -} + { + var _type = Component.type; + var _innerPropTypes = _type.propTypes; -function recordCommitTime() { - commitTime = now(); -} + if (_innerPropTypes) { + // Inner memo component props aren't currently validated in createElement. + // We could move it there, but we'd still need this for lazy code path. + checkPropTypes( + _innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(_type) + ); + } + } -function startProfilerTimer(fiber) { - profilerStartTime = now(); + var currentChild = current.child; // This is always exactly one child - if (fiber.actualStartTime < 0) { - fiber.actualStartTime = now(); - } -} + var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( + current, + renderLanes + ); -function stopProfilerTimerIfRunning(fiber) { - profilerStartTime = -1; -} + if (!hasScheduledUpdateOrContext) { + // This will be the props with resolved defaultProps, + // unlike current.memoizedProps which will be the unresolved ones. + var prevProps = currentChild.memoizedProps; // Default to shallow comparison -function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { - if (profilerStartTime >= 0) { - var elapsedTime = now() - profilerStartTime; - fiber.actualDuration += elapsedTime; + var compare = Component.compare; + compare = compare !== null ? compare : shallowEqual; - if (overrideBaseTime) { - fiber.selfBaseDuration = elapsedTime; - } + if ( + compare(prevProps, nextProps) && + current.ref === workInProgress.ref + ) { + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + } + } // React DevTools reads this flag. - profilerStartTime = -1; - } -} + workInProgress.flags |= PerformedWork; + var newChild = createWorkInProgress(currentChild, nextProps); + newChild.ref = workInProgress.ref; + newChild.return = workInProgress; + workInProgress.child = newChild; + return newChild; + } -function recordLayoutEffectDuration(fiber) { - if (layoutEffectStartTime >= 0) { - var elapsedTime = now() - layoutEffectStartTime; - layoutEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor - // Or the root (for the DevTools Profiler to read) + function updateSimpleMemoComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ) { + // TODO: current can be non-null here even if the component + // hasn't yet mounted. This happens when the inner render suspends. + // We'll need to figure out if this is fine or can cause issues. + { + if (workInProgress.type !== workInProgress.elementType) { + // Lazy component props can't be validated in createElement + // because they're only guaranteed to be resolved here. + var outerMemoType = workInProgress.elementType; + + if (outerMemoType.$$typeof === REACT_LAZY_TYPE) { + // We warn when you define propTypes on lazy() + // so let's just skip over it to find memo() outer wrapper. + // Inner props for memo are validated later. + var lazyComponent = outerMemoType; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - var parentFiber = fiber.return; + try { + outerMemoType = init(payload); + } catch (x) { + outerMemoType = null; + } // Inner propTypes will be validated in the function component path. + + var outerPropTypes = outerMemoType && outerMemoType.propTypes; + + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + nextProps, // Resolved (SimpleMemoComponent has no defaultProps) + "prop", + getComponentNameFromType(outerMemoType) + ); + } + } + } + } - while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; - root.effectDuration += elapsedTime; - return; + if (current !== null) { + var prevProps = current.memoizedProps; - case Profiler: - var parentStateNode = parentFiber.stateNode; - parentStateNode.effectDuration += elapsedTime; - return; + if ( + shallowEqual(prevProps, nextProps) && + current.ref === workInProgress.ref && // Prevent bailout if the implementation changed due to hot reload. + workInProgress.type === current.type + ) { + didReceiveUpdate = false; // The props are shallowly equal. Reuse the previous props object, like we + // would during a normal fiber bailout. + // + // We don't have strong guarantees that the props object is referentially + // equal during updates where we can't bail out anyway — like if the props + // are shallowly equal, but there's a local state or context update in the + // same batch. + // + // However, as a principle, we should aim to make the behavior consistent + // across different ways of memoizing a component. For example, React.memo + // has a different internal Fiber layout if you pass a normal function + // component (SimpleMemoComponent) versus if you pass a different type + // like forwardRef (MemoComponent). But this is an implementation detail. + // Wrapping a component in forwardRef (or React.lazy, etc) shouldn't + // affect whether the props object is reused during a bailout. + + workInProgress.pendingProps = nextProps = prevProps; + + if (!checkScheduledUpdateOrContext(current, renderLanes)) { + // The pending lanes were cleared at the beginning of beginWork. We're + // about to bail out, but there might be other lanes that weren't + // included in the current render. Usually, the priority level of the + // remaining updates is accumulated during the evaluation of the + // component (i.e. when processing the update queue). But since since + // we're bailing out early *without* evaluating the component, we need + // to account for it here, too. Reset to the value of the current fiber. + // NOTE: This only applies to SimpleMemoComponent, not MemoComponent, + // because a MemoComponent fiber does not have hooks or an update queue; + // rather, it wraps around an inner component, which may or may not + // contains hooks. + // TODO: Move the reset at in beginWork out of the common path so that + // this is no longer necessary. + workInProgress.lanes = current.lanes; + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + } else if ( + (current.flags & ForceUpdateForLegacySuspense) !== + NoFlags$1 + ) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; + } + } } - parentFiber = parentFiber.return; + return updateFunctionComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ); } - } -} -function recordPassiveEffectDuration(fiber) { - if (passiveEffectStartTime >= 0) { - var elapsedTime = now() - passiveEffectStartTime; - passiveEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor - // Or the root (for the DevTools Profiler to read) + function updateOffscreenComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + var nextIsDetached = + (workInProgress.stateNode._pendingVisibility & OffscreenDetached) !== 0; + var prevState = current !== null ? current.memoizedState : null; + markRef$1(current, workInProgress); - var parentFiber = fiber.return; + if ( + nextProps.mode === "hidden" || + nextProps.mode === "unstable-defer-without-hiding" || + nextIsDetached + ) { + // Rendering a hidden tree. + var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags$1; - while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; + if (didSuspend) { + // Something suspended inside a hidden tree + // Include the base lanes from the last render + var nextBaseLanes = + prevState !== null + ? mergeLanes(prevState.baseLanes, renderLanes) + : renderLanes; - if (root !== null) { - root.passiveEffectDuration += elapsedTime; + if (current !== null) { + // Reset to the current children + var currentChild = (workInProgress.child = current.child); // The current render suspended, but there may be other lanes with + // pending work. We can't read `childLanes` from the current Offscreen + // fiber because we reset it when it was deferred; however, we can read + // the pending lanes from the child fibers. + + var currentChildLanes = NoLanes; + + while (currentChild !== null) { + currentChildLanes = mergeLanes( + mergeLanes(currentChildLanes, currentChild.lanes), + currentChild.childLanes + ); + currentChild = currentChild.sibling; + } + + var lanesWeJustAttempted = nextBaseLanes; + var remainingChildLanes = removeLanes( + currentChildLanes, + lanesWeJustAttempted + ); + workInProgress.childLanes = remainingChildLanes; + } else { + workInProgress.childLanes = NoLanes; + workInProgress.child = null; } - return; + return deferHiddenOffscreenComponent( + current, + workInProgress, + nextBaseLanes, + renderLanes + ); + } - case Profiler: - var parentStateNode = parentFiber.stateNode; + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + // In legacy sync mode, don't defer the subtree. Render it now. + // TODO: Consider how Offscreen should work with transitions in the future + var nextState = { + baseLanes: NoLanes, + cachePool: null + }; + workInProgress.memoizedState = nextState; - if (parentStateNode !== null) { - // Detached fibers have their state node cleared out. - // In this case, the return pointer is also cleared out, - // so we won't be able to report the time spent in this Profiler's subtree. - parentStateNode.passiveEffectDuration += elapsedTime; + { + // push the cache pool even though we're going to bail out + // because otherwise there'd be a context mismatch + if (current !== null) { + pushTransition(workInProgress, null, null); + } } - return; - } + reuseHiddenContextOnStack(workInProgress); + pushOffscreenSuspenseHandler(workInProgress); + } else if (!includesSomeLane(renderLanes, OffscreenLane)) { + // We're hidden, and we're not rendering at Offscreen. We will bail out + // and resume this tree later. + // Schedule this fiber to re-render at Offscreen priority + workInProgress.lanes = workInProgress.childLanes = + laneToLanes(OffscreenLane); // Include the base lanes from the last render + + var _nextBaseLanes = + prevState !== null + ? mergeLanes(prevState.baseLanes, renderLanes) + : renderLanes; + + return deferHiddenOffscreenComponent( + current, + workInProgress, + _nextBaseLanes, + renderLanes + ); + } else { + // This is the second render. The surrounding visible content has already + // committed. Now we resume rendering the hidden tree. + // Rendering at offscreen, so we can clear the base lanes. + var _nextState = { + baseLanes: NoLanes, + cachePool: null + }; + workInProgress.memoizedState = _nextState; - parentFiber = parentFiber.return; - } - } -} + if (current !== null) { + // If the render that spawned this one accessed the cache pool, resume + // using the same cache. Unless the parent changed, since that means + // there was a refresh. + var prevCachePool = prevState !== null ? prevState.cachePool : null; // TODO: Consider if and how Offscreen pre-rendering should + // be attributed to the transition that spawned it -function startLayoutEffectTimer() { - layoutEffectStartTime = now(); -} + pushTransition(workInProgress, prevCachePool, null); + } // Push the lanes that were skipped when we bailed out. -function startPassiveEffectTimer() { - passiveEffectStartTime = now(); -} + if (prevState !== null) { + pushHiddenContext(workInProgress, prevState); + } else { + reuseHiddenContextOnStack(workInProgress); + } -function transferActualDuration(fiber) { - // Transfer time spent rendering these children so we don't lose it - // after we rerender. This is used as a helper in special cases - // where we should count the work of multiple passes. - var child = fiber.child; - - while (child) { - // $FlowFixMe[unsafe-addition] addition with possible null/undefined value - fiber.actualDuration += child.actualDuration; - child = child.sibling; - } -} + pushOffscreenSuspenseHandler(workInProgress); + } + } else { + // Rendering a visible tree. + if (prevState !== null) { + // We're going from hidden -> visible. + var _prevCachePool = null; -function resolveDefaultProps(Component, baseProps) { - if (Component && Component.defaultProps) { - // Resolve default props. Taken from ReactElement - var props = assign({}, baseProps); - var defaultProps = Component.defaultProps; + { + // If the render that spawned this one accessed the cache pool, resume + // using the same cache. Unless the parent changed, since that means + // there was a refresh. + _prevCachePool = prevState.cachePool; + } - for (var propName in defaultProps) { - if (props[propName] === undefined) { - props[propName] = defaultProps[propName]; - } - } + var transitions = null; - return props; - } + if (enableTransitionTracing) { + // We have now gone from hidden to visible, so any transitions should + // be added to the stack to get added to any Offscreen/suspense children + var instance = workInProgress.stateNode; - return baseProps; -} + if (instance !== null && instance._transitions != null) { + transitions = Array.from(instance._transitions); + } + } -var fakeInternalInstance = {}; -var didWarnAboutStateAssignmentForComponent; -var didWarnAboutUninitializedState; -var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate; -var didWarnAboutLegacyLifecyclesAndDerivedState; -var didWarnAboutUndefinedDerivedState; -var didWarnAboutDirectlyAssigningPropsToState; -var didWarnAboutInvalidateContextType; -var didWarnOnInvalidCallback; - -{ - didWarnAboutStateAssignmentForComponent = new Set(); - didWarnAboutUninitializedState = new Set(); - didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set(); - didWarnAboutLegacyLifecyclesAndDerivedState = new Set(); - didWarnAboutDirectlyAssigningPropsToState = new Set(); - didWarnAboutUndefinedDerivedState = new Set(); - didWarnAboutInvalidateContextType = new Set(); - didWarnOnInvalidCallback = new Set(); // This is so gross but it's at least non-critical and can be removed if - // it causes problems. This is meant to give a nicer error message for - // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component, - // ...)) which otherwise throws a "_processChildContext is not a function" - // exception. - - Object.defineProperty(fakeInternalInstance, "_processChildContext", { - enumerable: false, - value: function () { - 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)." - ); - } - }); - Object.freeze(fakeInternalInstance); -} + pushTransition(workInProgress, _prevCachePool, transitions); // Push the lanes that were skipped when we bailed out. -function warnOnInvalidCallback(callback, callerName) { - { - if (callback === null || typeof callback === "function") { - return; - } + pushHiddenContext(workInProgress, prevState); + reuseSuspenseHandlerOnStack(workInProgress); // Since we're not hidden anymore, reset the state - var key = callerName + "_" + callback; + workInProgress.memoizedState = null; + } else { + // We weren't previously hidden, and we still aren't, so there's nothing + // special to do. Need to push to the stack regardless, though, to avoid + // a push/pop misalignment. + { + // If the render that spawned this one accessed the cache pool, resume + // using the same cache. Unless the parent changed, since that means + // there was a refresh. + if (current !== null) { + pushTransition(workInProgress, null, null); + } + } // We're about to bail out, but we need to push this to the stack anyway + // to avoid a push/pop misalignment. - if (!didWarnOnInvalidCallback.has(key)) { - didWarnOnInvalidCallback.add(key); + reuseHiddenContextOnStack(workInProgress); + reuseSuspenseHandlerOnStack(workInProgress); + } + } - error( - "%s(...): Expected the last optional `callback` argument to be a " + - "function. Instead received: %s.", - callerName, - callback - ); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - } -} -function warnOnUndefinedDerivedState(type, partialState) { - { - if (partialState === undefined) { - var componentName = getComponentNameFromType(type) || "Component"; + function deferHiddenOffscreenComponent( + current, + workInProgress, + nextBaseLanes, + renderLanes + ) { + var nextState = { + baseLanes: nextBaseLanes, + // Save the cache pool so we can resume later. + cachePool: getOffscreenDeferredCache() + }; + workInProgress.memoizedState = nextState; + + { + // push the cache pool even though we're going to bail out + // because otherwise there'd be a context mismatch + if (current !== null) { + pushTransition(workInProgress, null, null); + } + } // We're about to bail out, but we need to push this to the stack anyway + // to avoid a push/pop misalignment. - if (!didWarnAboutUndefinedDerivedState.has(componentName)) { - didWarnAboutUndefinedDerivedState.add(componentName); + reuseHiddenContextOnStack(workInProgress); + pushOffscreenSuspenseHandler(workInProgress); - error( - "%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. " + - "You have returned undefined.", - componentName + if (enableLazyContextPropagation && current !== null) { + // Since this tree will resume rendering in a separate render, we need + // to propagate parent contexts now so we don't lose track of which + // ones changed. + propagateParentContextChangesToDeferredTree( + current, + workInProgress, + renderLanes ); } - } - } -} - -function applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - nextProps -) { - var prevState = workInProgress.memoizedState; - var partialState = getDerivedStateFromProps(nextProps, prevState); - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + return null; + } // Note: These happen to have identical begin phases, for now. We shouldn't hold + // ourselves to this constraint, though. If the behavior diverges, we should + // fork the function. - try { - // Invoke the function an extra time to help detect side-effects. - partialState = getDerivedStateFromProps(nextProps, prevState); - } finally { - setIsStrictModeForDevtools(false); - } - } + var updateLegacyHiddenComponent = updateOffscreenComponent; - warnOnUndefinedDerivedState(ctor, partialState); - } // Merge the partial state and the previous state. + function updateCacheComponent(current, workInProgress, renderLanes) { + prepareToReadContext(workInProgress, renderLanes); + var parentCache = readContext(CacheContext); - var memoizedState = - partialState === null || partialState === undefined - ? prevState - : assign({}, prevState, partialState); - workInProgress.memoizedState = memoizedState; // Once the update queue is empty, persist the derived state onto the - // base state. + if (current === null) { + // Initial mount. Request a fresh cache from the pool. + var freshCache = requestCacheFromPool(renderLanes); + var initialState = { + parent: parentCache, + cache: freshCache + }; + workInProgress.memoizedState = initialState; + initializeUpdateQueue(workInProgress); + pushCacheProvider(workInProgress, freshCache); + } else { + // Check for updates + if (includesSomeLane(current.lanes, renderLanes)) { + cloneUpdateQueue(current, workInProgress); + processUpdateQueue(workInProgress, null, null, renderLanes); + } - if (workInProgress.lanes === NoLanes) { - // Queue is always non-null for classes - var updateQueue = workInProgress.updateQueue; - updateQueue.baseState = memoizedState; - } -} + var prevState = current.memoizedState; + var nextState = workInProgress.memoizedState; // Compare the new parent cache to the previous to see detect there was + // a refresh. + + if (prevState.parent !== parentCache) { + // Refresh in parent. Update the parent. + var derivedState = { + parent: parentCache, + cache: parentCache + }; // Copied from getDerivedStateFromProps implementation. Once the update + // queue is empty, persist the derived state onto the base state. + + workInProgress.memoizedState = derivedState; + + if (workInProgress.lanes === NoLanes) { + var updateQueue = workInProgress.updateQueue; + workInProgress.memoizedState = updateQueue.baseState = derivedState; + } -var classComponentUpdater = { - isMounted: isMounted, - // $FlowFixMe[missing-local-annot] - enqueueSetState: function (inst, payload, callback) { - var fiber = get(inst); - var lane = requestUpdateLane(fiber); - var update = createUpdate(lane); - update.payload = payload; + pushCacheProvider(workInProgress, parentCache); // No need to propagate a context change because the refreshed parent + // already did. + } else { + // The parent didn't refresh. Now check if this cache did. + var nextCache = nextState.cache; + pushCacheProvider(workInProgress, nextCache); - if (callback !== undefined && callback !== null) { - { - warnOnInvalidCallback(callback, "setState"); + if (nextCache !== prevState.cache) { + // This cache refreshed. Propagate a context change. + propagateContextChange(workInProgress, CacheContext, renderLanes); + } + } } - update.callback = callback; - } + var nextChildren = workInProgress.pendingProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } // This should only be called if the name changes - var root = enqueueUpdate(fiber, update, lane); + function updateTracingMarkerComponent( + current, + workInProgress, + renderLanes + ) { + if (!enableTransitionTracing) { + return null; + } // TODO: (luna) Only update the tracing marker if it's newly rendered or it's name changed. + // A tracing marker is only associated with the transitions that rendered + // or updated it, so we can create a new set of transitions each time - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane); - entangleTransitions(root, fiber, lane); - } + if (current === null) { + var currentTransitions = getPendingTransitions(); - { - if (enableDebugTracing) { - if (fiber.mode & DebugTracingMode) { - var name = getComponentNameFromFiber(fiber) || "Unknown"; - logStateUpdateScheduled(name, lane, payload); + if (currentTransitions !== null) { + var markerInstance = { + tag: TransitionTracingMarker, + transitions: new Set(currentTransitions), + pendingBoundaries: null, + name: workInProgress.pendingProps.name, + aborts: null + }; + workInProgress.stateNode = markerInstance; // We call the marker complete callback when all child suspense boundaries resolve. + // We do this in the commit phase on Offscreen. If the marker has no child suspense + // boundaries, we need to schedule a passive effect to make sure we call the marker + // complete callback. + + workInProgress.flags |= Passive$1; + } + } else { + { + if (current.memoizedProps.name !== workInProgress.pendingProps.name) { + error( + "Changing the name of a tracing marker after mount is not supported. " + + "To remount the tracing marker, pass it a new key." + ); + } } } - } - if (enableSchedulingProfiler) { - markStateUpdateScheduled(fiber, lane); - } - }, - enqueueReplaceState: function (inst, payload, callback) { - var fiber = get(inst); - var lane = requestUpdateLane(fiber); - var update = createUpdate(lane); - update.tag = ReplaceState; - update.payload = payload; + var instance = workInProgress.stateNode; - if (callback !== undefined && callback !== null) { - { - warnOnInvalidCallback(callback, "replaceState"); + if (instance !== null) { + pushMarkerInstance(workInProgress, instance); } - update.callback = callback; - } - - var root = enqueueUpdate(fiber, update, lane); - - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane); - entangleTransitions(root, fiber, lane); + var nextChildren = workInProgress.pendingProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - { - if (enableDebugTracing) { - if (fiber.mode & DebugTracingMode) { - var name = getComponentNameFromFiber(fiber) || "Unknown"; - logStateUpdateScheduled(name, lane, payload); - } - } + function updateFragment(current, workInProgress, renderLanes) { + var nextChildren = workInProgress.pendingProps; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - if (enableSchedulingProfiler) { - markStateUpdateScheduled(fiber, lane); + function updateMode(current, workInProgress, renderLanes) { + var nextChildren = workInProgress.pendingProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - }, - // $FlowFixMe[missing-local-annot] - enqueueForceUpdate: function (inst, callback) { - var fiber = get(inst); - var lane = requestUpdateLane(fiber); - var update = createUpdate(lane); - update.tag = ForceUpdate; - if (callback !== undefined && callback !== null) { + function updateProfiler(current, workInProgress, renderLanes) { { - warnOnInvalidCallback(callback, "forceUpdate"); + workInProgress.flags |= Update; + + { + // Reset effect durations for the next eventual effect phase. + // These are reset during render to allow the DevTools commit hook a chance to read them, + var stateNode = workInProgress.stateNode; + stateNode.effectDuration = 0; + stateNode.passiveEffectDuration = 0; + } } - update.callback = callback; + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - var root = enqueueUpdate(fiber, update, lane); - - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, lane); - entangleTransitions(root, fiber, lane); - } + function markRef$1(current, workInProgress) { + var ref = workInProgress.ref; - { - if (enableDebugTracing) { - if (fiber.mode & DebugTracingMode) { - var name = getComponentNameFromFiber(fiber) || "Unknown"; - logForceUpdateScheduled(name, lane); - } + if ( + (current === null && ref !== null) || + (current !== null && current.ref !== ref) + ) { + // Schedule a Ref effect + workInProgress.flags |= Ref; + workInProgress.flags |= RefStatic; } } - if (enableSchedulingProfiler) { - markForceUpdateScheduled(fiber, lane); - } - } -}; + function updateFunctionComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ) { + { + if (workInProgress.type !== workInProgress.elementType) { + // Lazy component props can't be validated in createElement + // because they're only guaranteed to be resolved here. + var innerPropTypes = Component.propTypes; -function checkShouldComponentUpdate( - workInProgress, - ctor, - oldProps, - newProps, - oldState, - newState, - nextContext -) { - var instance = workInProgress.stateNode; + if (innerPropTypes) { + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(Component) + ); + } + } + } - if (typeof instance.shouldComponentUpdate === "function") { - var shouldUpdate = instance.shouldComponentUpdate( - newProps, - newState, - nextContext - ); + var context; - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + var nextChildren; + prepareToReadContext(workInProgress, renderLanes); - try { - // Invoke the function an extra time to help detect side-effects. - shouldUpdate = instance.shouldComponentUpdate( - newProps, - newState, - nextContext - ); - } finally { - setIsStrictModeForDevtools(false); - } + if (enableSchedulingProfiler) { + markComponentRenderStarted(workInProgress); } - if (shouldUpdate === undefined) { - error( - "%s.shouldComponentUpdate(): Returned undefined instead of a " + - "boolean value. Make sure to return true or false.", - getComponentNameFromType(ctor) || "Component" + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + nextChildren = renderWithHooks( + current, + workInProgress, + Component, + nextProps, + context, + renderLanes ); + setIsRendering(false); } - } - return shouldUpdate; - } - - if (ctor.prototype && ctor.prototype.isPureReactComponent) { - return ( - !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) - ); - } - - return true; -} - -function checkClassInstance(workInProgress, ctor, newProps) { - var instance = workInProgress.stateNode; - - { - var name = getComponentNameFromType(ctor) || "Component"; - var renderPresent = instance.render; + if (enableSchedulingProfiler) { + markComponentRenderStopped(); + } - if (!renderPresent) { - if (ctor.prototype && typeof ctor.prototype.render === "function") { - error( - "%s(...): No `render` method found on the returned component " + - "instance: did you accidentally return an object from the constructor?", - name - ); - } else { - error( - "%s(...): No `render` method found on the returned component " + - "instance: you may have forgotten to define `render`.", - name + if (current !== null && !didReceiveUpdate) { + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes ); } - } - if ( - instance.getInitialState && - !instance.getInitialState.isReactClassApproved && - !instance.state - ) { - 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 - ); + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - if ( - instance.getDefaultProps && - !instance.getDefaultProps.isReactClassApproved + function replayFunctionComponent( + current, + workInProgress, + nextProps, + Component, + secondArg, + renderLanes ) { - 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 - ); - } + // This function is used to replay a component that previously suspended, + // after its data resolves. It's a simplified version of + // updateFunctionComponent that reuses the hooks from the previous attempt. + prepareToReadContext(workInProgress, renderLanes); - if (instance.propTypes) { - error( - "propTypes was defined as an instance property on %s. Use a static " + - "property to define propTypes instead.", - name - ); - } + if (enableSchedulingProfiler) { + markComponentRenderStarted(workInProgress); + } - if (instance.contextType) { - error( - "contextType was defined as an instance property on %s. Use a static " + - "property to define contextType instead.", - name + var nextChildren = replaySuspendedComponentWithHooks( + current, + workInProgress, + Component, + nextProps, + secondArg ); - } - { - if (ctor.childContextTypes) { - error( - "%s uses the legacy childContextTypes API which is no longer supported. " + - "Use React.createContext() instead.", - name - ); + if (enableSchedulingProfiler) { + markComponentRenderStopped(); } - if (ctor.contextTypes) { - error( - "%s uses the legacy contextTypes API which is no longer supported. " + - "Use React.createContext() with static contextType instead.", - name + if (current !== null && !didReceiveUpdate) { + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes ); } - } - if (typeof instance.componentShouldUpdate === "function") { - 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 - ); + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - if ( - ctor.prototype && - ctor.prototype.isPureReactComponent && - typeof instance.shouldComponentUpdate !== "undefined" + function updateClassComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes ) { - 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" - ); - } + { + // This is used by DevTools to force a boundary to error. + switch (shouldError(workInProgress)) { + case false: { + var _instance = workInProgress.stateNode; + var ctor = workInProgress.type; // TODO This way of resetting the error boundary state is a hack. + // Is there a better way to do this? + + var tempInstance = new ctor( + workInProgress.memoizedProps, + _instance.context + ); + var state = tempInstance.state; - if (typeof instance.componentDidUnmount === "function") { - error( - "%s has a method called " + - "componentDidUnmount(). But there is no such lifecycle method. " + - "Did you mean componentWillUnmount()?", - name - ); - } + _instance.updater.enqueueSetState(_instance, state, null); - if (typeof instance.componentDidReceiveProps === "function") { - 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 - ); - } + break; + } - if (typeof instance.componentWillRecieveProps === "function") { - error( - "%s has a method called " + - "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", - name - ); - } + case true: { + workInProgress.flags |= DidCapture; + workInProgress.flags |= ShouldCapture; // eslint-disable-next-line react-internal/prod-error-codes - if (typeof instance.UNSAFE_componentWillRecieveProps === "function") { - error( - "%s has a method called " + - "UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?", - name - ); - } + var error$1 = new Error("Simulated error coming from DevTools"); + var lane = pickArbitraryLane(renderLanes); + workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); // Schedule the error boundary to re-render using updated state + + var update = createClassErrorUpdate( + workInProgress, + createCapturedValueAtFiber(error$1, workInProgress), + lane + ); + enqueueCapturedUpdate(workInProgress, update); + break; + } + } - var hasMutatedProps = instance.props !== newProps; + if (workInProgress.type !== workInProgress.elementType) { + // Lazy component props can't be validated in createElement + // because they're only guaranteed to be resolved here. + var innerPropTypes = Component.propTypes; - if (instance.props !== undefined && hasMutatedProps) { - error( - "%s(...): When calling super() in `%s`, make sure to pass " + - "up the same props that your component's constructor was passed.", - name, - name - ); - } + if (innerPropTypes) { + checkPropTypes( + innerPropTypes, + nextProps, // Resolved props + "prop", + getComponentNameFromType(Component) + ); + } + } + } // Push context providers early to prevent context stack mismatches. + // During mounting we don't know the child context yet as the instance doesn't exist. + // We will invalidate the child context in finishClassComponent() right after rendering. - if (instance.defaultProps) { - 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 - ); - } + var hasContext; - if ( - typeof instance.getSnapshotBeforeUpdate === "function" && - typeof instance.componentDidUpdate !== "function" && - !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor) - ) { - didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor); + if (isContextProvider()) { + hasContext = true; + } else { + hasContext = false; + } - error( - "%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). " + - "This component defines getSnapshotBeforeUpdate() only.", - getComponentNameFromType(ctor) - ); - } + prepareToReadContext(workInProgress, renderLanes); + var instance = workInProgress.stateNode; + var shouldUpdate; - if (typeof instance.getDerivedStateFromProps === "function") { - error( - "%s: getDerivedStateFromProps() is defined as an instance method " + - "and will be ignored. Instead, declare it as a static method.", - name - ); - } + if (instance === null) { + resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); // In the initial pass we might need to construct the instance. - if (typeof instance.getDerivedStateFromError === "function") { - error( - "%s: getDerivedStateFromError() is defined as an instance method " + - "and will be ignored. Instead, declare it as a static method.", - name - ); - } + constructClassInstance(workInProgress, Component, nextProps); + mountClassInstance(workInProgress, Component, nextProps, renderLanes); + shouldUpdate = true; + } else if (current === null) { + // In a resume, we'll already have an instance we can reuse. + shouldUpdate = resumeMountClassInstance( + workInProgress, + Component, + nextProps, + renderLanes + ); + } else { + shouldUpdate = updateClassInstance( + current, + workInProgress, + Component, + nextProps, + renderLanes + ); + } - if (typeof ctor.getSnapshotBeforeUpdate === "function") { - error( - "%s: getSnapshotBeforeUpdate() is defined as a static method " + - "and will be ignored. Instead, declare it as an instance method.", - name + var nextUnitOfWork = finishClassComponent( + current, + workInProgress, + Component, + shouldUpdate, + hasContext, + renderLanes ); - } - var state = instance.state; + { + var inst = workInProgress.stateNode; + + if (shouldUpdate && inst.props !== nextProps) { + if (!didWarnAboutReassigningProps) { + 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" + ); + } + + didWarnAboutReassigningProps = true; + } + } - if (state && (typeof state !== "object" || isArray(state))) { - error("%s.state: must be set to an object or null", name); + return nextUnitOfWork; } - if ( - typeof instance.getChildContext === "function" && - typeof ctor.childContextTypes !== "object" + function finishClassComponent( + current, + workInProgress, + Component, + shouldUpdate, + hasContext, + renderLanes ) { - error( - "%s.getChildContext(): childContextTypes must be defined in order to " + - "use getChildContext().", - name - ); - } - } -} + // Refs should update even if shouldComponentUpdate returns false + markRef$1(current, workInProgress); + var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags$1; + + if (!shouldUpdate && !didCaptureError) { + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + } + + var instance = workInProgress.stateNode; // Rerender + + ReactCurrentOwner$1.current = workInProgress; + var nextChildren; + + if ( + didCaptureError && + typeof Component.getDerivedStateFromError !== "function" + ) { + // If we captured an error, but getDerivedStateFromError is not defined, + // unmount all the children. componentDidCatch will schedule an update to + // re-render a fallback. This is temporary until we migrate everyone to + // the new API. + // TODO: Warn in a future release. + nextChildren = null; -function adoptClassInstance(workInProgress, instance) { - instance.updater = classComponentUpdater; - workInProgress.stateNode = instance; // The instance needs access to the fiber so that it can schedule updates + { + stopProfilerTimerIfRunning(); + } + } else { + if (enableSchedulingProfiler) { + markComponentRenderStarted(workInProgress); + } - set(instance, workInProgress); + { + setIsRendering(true); + nextChildren = instance.render(); - { - instance._reactInternalInstance = fakeInternalInstance; - } -} + if (workInProgress.mode & StrictLegacyMode) { + setIsStrictModeForDevtools(true); -function constructClassInstance(workInProgress, ctor, props) { - var context = emptyContextObject; - var contextType = ctor.contextType; - - { - if ("contextType" in ctor) { - var isValid = // Allow null for conditional declaration - contextType === null || - (contextType !== undefined && - contextType.$$typeof === REACT_CONTEXT_TYPE && - contextType._context === undefined); // Not a - - if (!isValid && !didWarnAboutInvalidateContextType.has(ctor)) { - didWarnAboutInvalidateContextType.add(ctor); - var addendum = ""; - - if (contextType === undefined) { - 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."; - } else if (typeof contextType !== "object") { - addendum = " However, it is set to a " + typeof contextType + "."; - } else if (contextType.$$typeof === REACT_PROVIDER_TYPE) { - addendum = " Did you accidentally pass the Context.Provider instead?"; - } else if (contextType._context !== undefined) { - // - addendum = " Did you accidentally pass the Context.Consumer instead?"; - } else { - addendum = - " However, it is set to an object with keys {" + - Object.keys(contextType).join(", ") + - "}."; + try { + instance.render(); + } finally { + setIsStrictModeForDevtools(false); + } + } + + setIsRendering(false); } - error( - "%s defines an invalid contextType. " + - "contextType should point to the Context object returned by React.createContext().%s", - getComponentNameFromType(ctor) || "Component", - addendum - ); - } - } - } + if (enableSchedulingProfiler) { + markComponentRenderStopped(); + } + } // React DevTools reads this flag. - if (typeof contextType === "object" && contextType !== null) { - context = readContext(contextType); - } + workInProgress.flags |= PerformedWork; - var instance = new ctor(props, context); // Instantiate twice to help detect side-effects. + if (current !== null && didCaptureError) { + // If we're recovering from an error, reconcile without reusing any of + // the existing children. Conceptually, the normal children and the children + // that are shown on error are two different sets, so we shouldn't reuse + // normal children even if their identities match. + forceUnmountCurrentAndReconcile( + current, + workInProgress, + nextChildren, + renderLanes + ); + } else { + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + } // Memoize state using the values we just used to render. + // TODO: Restructure so we never read values from the instance. - { - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + workInProgress.memoizedState = instance.state; // The context might have changed so we need to recalculate it. - try { - instance = new ctor(props, context); // eslint-disable-line no-new - } finally { - setIsStrictModeForDevtools(false); - } + return workInProgress.child; } - } - var state = (workInProgress.memoizedState = - instance.state !== null && instance.state !== undefined - ? instance.state - : null); - adoptClassInstance(workInProgress, instance); + function pushHostRootContext(workInProgress) { + var root = workInProgress.stateNode; - { - if (typeof ctor.getDerivedStateFromProps === "function" && state === null) { - var componentName = getComponentNameFromType(ctor) || "Component"; - - if (!didWarnAboutUninitializedState.has(componentName)) { - didWarnAboutUninitializedState.add(componentName); - - 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 - ); - } - } // If new component APIs are defined, "unsafe" lifecycles won't be called. - // Warn about these lifecycles if they are present. - // Don't warn about react-lifecycles-compat polyfilled methods though. + pushHostContainer(workInProgress, root.containerInfo); + } - if ( - typeof ctor.getDerivedStateFromProps === "function" || - typeof instance.getSnapshotBeforeUpdate === "function" - ) { - var foundWillMountName = null; - var foundWillReceivePropsName = null; - var foundWillUpdateName = null; + function updateHostRoot(current, workInProgress, renderLanes) { + pushHostRootContext(workInProgress); - if ( - typeof instance.componentWillMount === "function" && - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - foundWillMountName = "componentWillMount"; - } else if (typeof instance.UNSAFE_componentWillMount === "function") { - foundWillMountName = "UNSAFE_componentWillMount"; + if (current === null) { + throw new Error("Should have a current fiber. This is a bug in React."); } - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== true - ) { - foundWillReceivePropsName = "componentWillReceiveProps"; - } else if ( - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - foundWillReceivePropsName = "UNSAFE_componentWillReceiveProps"; - } + var nextProps = workInProgress.pendingProps; + var prevState = workInProgress.memoizedState; + var prevChildren = prevState.element; + cloneUpdateQueue(current, workInProgress); + processUpdateQueue(workInProgress, nextProps, null, renderLanes); + var nextState = workInProgress.memoizedState; + pushRootTransition(workInProgress); - if ( - typeof instance.componentWillUpdate === "function" && - instance.componentWillUpdate.__suppressDeprecationWarning !== true - ) { - foundWillUpdateName = "componentWillUpdate"; - } else if (typeof instance.UNSAFE_componentWillUpdate === "function") { - foundWillUpdateName = "UNSAFE_componentWillUpdate"; + if (enableTransitionTracing) { + pushRootMarkerInstance(workInProgress); } - if ( - foundWillMountName !== null || - foundWillReceivePropsName !== null || - foundWillUpdateName !== null - ) { - var _componentName = getComponentNameFromType(ctor) || "Component"; + { + var nextCache = nextState.cache; + pushCacheProvider(workInProgress, nextCache); - var newApiName = - typeof ctor.getDerivedStateFromProps === "function" - ? "getDerivedStateFromProps()" - : "getSnapshotBeforeUpdate()"; + if (nextCache !== prevState.cache) { + // The root cache refreshed. + propagateContextChange(workInProgress, CacheContext, renderLanes); + } + } // Caution: React DevTools currently depends on this property + // being called "element". - if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName)) { - didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName); + var nextChildren = nextState.element; - 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 : "" + { + if (nextChildren === prevChildren) { + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes ); } + + reconcileChildren(current, workInProgress, nextChildren, renderLanes); } - } - } // Cache unmasked context so we can avoid recreating masked context unless necessary. - return instance; -} + return workInProgress.child; + } -function callComponentWillMount(workInProgress, instance) { - var oldState = instance.state; + function updateHostComponent$1(current, workInProgress, renderLanes) { + pushHostContext(workInProgress); - if (typeof instance.componentWillMount === "function") { - instance.componentWillMount(); - } + var type = workInProgress.type; + var nextProps = workInProgress.pendingProps; + var prevProps = current !== null ? current.memoizedProps : null; + var nextChildren = nextProps.children; + var isDirectTextChild = shouldSetTextContent(type, nextProps); - if (typeof instance.UNSAFE_componentWillMount === "function") { - instance.UNSAFE_componentWillMount(); - } + if (isDirectTextChild) { + // We special case a direct text child of a host node. This is a common + // case. We won't handle it as a reified child. We will instead handle + // this in the host environment that also has access to this prop. That + // avoids allocating another HostText fiber and traversing it. + nextChildren = null; + } else if (prevProps !== null && shouldSetTextContent(type, prevProps)) { + // If we're switching from a direct text child to a normal child, or to + // empty, we need to schedule the text content to be reset. + workInProgress.flags |= ContentReset; + } - if (oldState !== instance.state) { - { - error( - "%s.componentWillMount(): Assigning directly to this.state is " + - "deprecated (except inside a component's " + - "constructor). Use setState instead.", - getComponentNameFromFiber(workInProgress) || "Component" - ); + markRef$1(current, workInProgress); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } - classComponentUpdater.enqueueReplaceState(instance, instance.state, null); - } -} - -function callComponentWillReceiveProps( - workInProgress, - instance, - newProps, - nextContext -) { - var oldState = instance.state; + function updateHostText$1(current, workInProgress) { + // immediately after. - if (typeof instance.componentWillReceiveProps === "function") { - instance.componentWillReceiveProps(newProps, nextContext); - } - - if (typeof instance.UNSAFE_componentWillReceiveProps === "function") { - instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); - } + return null; + } - if (instance.state !== oldState) { - { - var componentName = - getComponentNameFromFiber(workInProgress) || "Component"; + function mountLazyComponent( + _current, + workInProgress, + elementType, + renderLanes + ) { + resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); + var props = workInProgress.pendingProps; + var lazyComponent = elementType; + var payload = lazyComponent._payload; + var init = lazyComponent._init; + var Component = init(payload); // Store the unwrapped component in the type. + + workInProgress.type = Component; + var resolvedTag = (workInProgress.tag = + resolveLazyComponentTag(Component)); + var resolvedProps = resolveDefaultProps(Component, props); + var child; + + switch (resolvedTag) { + case FunctionComponent: { + { + validateFunctionComponentInDev(workInProgress, Component); + workInProgress.type = Component = + resolveFunctionForHotReloading(Component); + } - if (!didWarnAboutStateAssignmentForComponent.has(componentName)) { - didWarnAboutStateAssignmentForComponent.add(componentName); + child = updateFunctionComponent( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; + } - error( - "%s.componentWillReceiveProps(): Assigning directly to " + - "this.state is deprecated (except inside a component's " + - "constructor). Use setState instead.", - componentName - ); - } - } + case ClassComponent: { + { + workInProgress.type = Component = + resolveClassForHotReloading(Component); + } - classComponentUpdater.enqueueReplaceState(instance, instance.state, null); - } -} // Invokes the mount life-cycles on a previously never rendered instance. + child = updateClassComponent( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; + } -function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { - { - checkClassInstance(workInProgress, ctor, newProps); - } + case ForwardRef: { + { + workInProgress.type = Component = + resolveForwardRefForHotReloading(Component); + } - var instance = workInProgress.stateNode; - instance.props = newProps; - instance.state = workInProgress.memoizedState; - instance.refs = {}; - initializeUpdateQueue(workInProgress); - var contextType = ctor.contextType; + child = updateForwardRef( + null, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + return child; + } - if (typeof contextType === "object" && contextType !== null) { - instance.context = readContext(contextType); - } else { - instance.context = emptyContextObject; - } + case MemoComponent: { + { + if (workInProgress.type !== workInProgress.elementType) { + var outerPropTypes = Component.propTypes; + + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + resolvedProps, // Resolved for outer only + "prop", + getComponentNameFromType(Component) + ); + } + } + } - { - if (instance.state === newProps) { - var componentName = getComponentNameFromType(ctor) || "Component"; + child = updateMemoComponent( + null, + workInProgress, + Component, + resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too + renderLanes + ); + return child; + } + } - if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) { - didWarnAboutDirectlyAssigningPropsToState.add(componentName); + var hint = ""; - 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 - ); - } - } + { + if ( + Component !== null && + typeof Component === "object" && + Component.$$typeof === REACT_LAZY_TYPE + ) { + hint = " Did you wrap a component in React.lazy() more than once?"; + } + } // This message intentionally doesn't mention ForwardRef or MemoComponent + // because the fact that it's a separate type of work is an + // implementation detail. - if (workInProgress.mode & StrictLegacyMode) { - ReactStrictModeWarnings.recordLegacyContextWarning( - workInProgress, - instance + 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) ); } - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings( + function mountIncompleteClassComponent( + _current, workInProgress, - instance - ); - } + Component, + nextProps, + renderLanes + ) { + resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); // Promote the fiber to a class and try rendering again. - instance.state = workInProgress.memoizedState; - var getDerivedStateFromProps = ctor.getDerivedStateFromProps; + workInProgress.tag = ClassComponent; // The rest of this function is a fork of `updateClassComponent` + // Push context providers early to prevent context stack mismatches. + // During mounting we don't know the child context yet as the instance doesn't exist. + // We will invalidate the child context in finishClassComponent() right after rendering. - if (typeof getDerivedStateFromProps === "function") { - applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - newProps - ); - instance.state = workInProgress.memoizedState; - } // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for components using the new APIs. - - if ( - typeof ctor.getDerivedStateFromProps !== "function" && - typeof instance.getSnapshotBeforeUpdate !== "function" && - (typeof instance.UNSAFE_componentWillMount === "function" || - typeof instance.componentWillMount === "function") - ) { - callComponentWillMount(workInProgress, instance); // If we had additional state updates during this life-cycle, let's - // process them now. - - processUpdateQueue(workInProgress, newProps, instance, renderLanes); - instance.state = workInProgress.memoizedState; - } - - if (typeof instance.componentDidMount === "function") { - workInProgress.flags |= Update | LayoutStatic; - } - - if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { - workInProgress.flags |= MountLayoutDev; - } -} + var hasContext; + + if (isContextProvider()) { + hasContext = true; + } else { + hasContext = false; + } -function resumeMountClassInstance(workInProgress, ctor, newProps, renderLanes) { - var instance = workInProgress.stateNode; - var oldProps = workInProgress.memoizedProps; - instance.props = oldProps; - var oldContext = instance.context; - var contextType = ctor.contextType; - var nextContext = emptyContextObject; - - if (typeof contextType === "object" && contextType !== null) { - nextContext = readContext(contextType); - } - - var getDerivedStateFromProps = ctor.getDerivedStateFromProps; - var hasNewLifecycles = - typeof getDerivedStateFromProps === "function" || - typeof instance.getSnapshotBeforeUpdate === "function"; // Note: During these life-cycles, instance.props/instance.state are what - // ever the previously attempted to render - not the "current". However, - // during componentDidUpdate we pass the "current" props. - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for components using the new APIs. - - if ( - !hasNewLifecycles && - (typeof instance.UNSAFE_componentWillReceiveProps === "function" || - typeof instance.componentWillReceiveProps === "function") - ) { - if (oldProps !== newProps || oldContext !== nextContext) { - callComponentWillReceiveProps( + prepareToReadContext(workInProgress, renderLanes); + constructClassInstance(workInProgress, Component, nextProps); + mountClassInstance(workInProgress, Component, nextProps, renderLanes); + return finishClassComponent( + null, workInProgress, - instance, - newProps, - nextContext + Component, + true, + hasContext, + renderLanes ); } - } - - resetHasForceUpdateBeforeProcessing(); - var oldState = workInProgress.memoizedState; - var newState = (instance.state = oldState); - processUpdateQueue(workInProgress, newProps, instance, renderLanes); - newState = workInProgress.memoizedState; - - if ( - oldProps === newProps && - oldState === newState && - !hasContextChanged() && - !checkHasForceUpdateAfterProcessing() - ) { - // If an update was already in progress, we should schedule an Update - // effect even though we're bailing out, so that cWU/cDU are called. - if (typeof instance.componentDidMount === "function") { - workInProgress.flags |= Update | LayoutStatic; - } - - if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { - workInProgress.flags |= MountLayoutDev; - } - - return false; - } - - if (typeof getDerivedStateFromProps === "function") { - applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - newProps - ); - newState = workInProgress.memoizedState; - } - var shouldUpdate = - checkHasForceUpdateAfterProcessing() || - checkShouldComponentUpdate( + function mountIndeterminateComponent( + _current, workInProgress, - ctor, - oldProps, - newProps, - oldState, - newState, - nextContext - ); - - if (shouldUpdate) { - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for components using the new APIs. - if ( - !hasNewLifecycles && - (typeof instance.UNSAFE_componentWillMount === "function" || - typeof instance.componentWillMount === "function") + Component, + renderLanes ) { - if (typeof instance.componentWillMount === "function") { - instance.componentWillMount(); - } + resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); + var props = workInProgress.pendingProps; + var context; - if (typeof instance.UNSAFE_componentWillMount === "function") { - instance.UNSAFE_componentWillMount(); - } - } + prepareToReadContext(workInProgress, renderLanes); + var value; - if (typeof instance.componentDidMount === "function") { - workInProgress.flags |= Update | LayoutStatic; - } - - if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { - workInProgress.flags |= MountLayoutDev; - } - } else { - // If an update was already in progress, we should schedule an Update - // effect even though we're bailing out, so that cWU/cDU are called. - if (typeof instance.componentDidMount === "function") { - workInProgress.flags |= Update | LayoutStatic; - } - - if ((workInProgress.mode & StrictEffectsMode) !== NoMode) { - workInProgress.flags |= MountLayoutDev; - } // If shouldComponentUpdate returned false, we should still update the - // memoized state to indicate that this work can be reused. - - workInProgress.memoizedProps = newProps; - workInProgress.memoizedState = newState; - } // Update the existing instance's state, props, and context pointers even - // if shouldComponentUpdate returns false. - - instance.props = newProps; - instance.state = newState; - instance.context = nextContext; - return shouldUpdate; -} // Invokes the update life-cycles and returns false if it shouldn't rerender. - -function updateClassInstance( - current, - workInProgress, - ctor, - newProps, - renderLanes -) { - var instance = workInProgress.stateNode; - cloneUpdateQueue(current, workInProgress); - var unresolvedOldProps = workInProgress.memoizedProps; - var oldProps = - workInProgress.type === workInProgress.elementType - ? unresolvedOldProps - : resolveDefaultProps(workInProgress.type, unresolvedOldProps); - instance.props = oldProps; - var unresolvedNewProps = workInProgress.pendingProps; - var oldContext = instance.context; - var contextType = ctor.contextType; - var nextContext = emptyContextObject; - - if (typeof contextType === "object" && contextType !== null) { - nextContext = readContext(contextType); - } - - var getDerivedStateFromProps = ctor.getDerivedStateFromProps; - var hasNewLifecycles = - typeof getDerivedStateFromProps === "function" || - typeof instance.getSnapshotBeforeUpdate === "function"; // Note: During these life-cycles, instance.props/instance.state are what - // ever the previously attempted to render - not the "current". However, - // during componentDidUpdate we pass the "current" props. - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for components using the new APIs. - - if ( - !hasNewLifecycles && - (typeof instance.UNSAFE_componentWillReceiveProps === "function" || - typeof instance.componentWillReceiveProps === "function") - ) { - if ( - unresolvedOldProps !== unresolvedNewProps || - oldContext !== nextContext - ) { - callComponentWillReceiveProps( - workInProgress, - instance, - newProps, - nextContext - ); - } - } - - resetHasForceUpdateBeforeProcessing(); - var oldState = workInProgress.memoizedState; - var newState = (instance.state = oldState); - processUpdateQueue(workInProgress, newProps, instance, renderLanes); - newState = workInProgress.memoizedState; - - if ( - unresolvedOldProps === unresolvedNewProps && - oldState === newState && - !hasContextChanged() && - !checkHasForceUpdateAfterProcessing() && - !( - enableLazyContextPropagation && - current !== null && - current.dependencies !== null && - checkIfContextChanged(current.dependencies) - ) - ) { - // If an update was already in progress, we should schedule an Update - // effect even though we're bailing out, so that cWU/cDU are called. - if (typeof instance.componentDidUpdate === "function") { - if ( - unresolvedOldProps !== current.memoizedProps || - oldState !== current.memoizedState - ) { - workInProgress.flags |= Update; + if (enableSchedulingProfiler) { + markComponentRenderStarted(workInProgress); } - } - if (typeof instance.getSnapshotBeforeUpdate === "function") { - if ( - unresolvedOldProps !== current.memoizedProps || - oldState !== current.memoizedState - ) { - workInProgress.flags |= Snapshot; - } - } + { + if ( + Component.prototype && + typeof Component.prototype.render === "function" + ) { + var componentName = getComponentNameFromType(Component) || "Unknown"; - return false; - } + if (!didWarnAboutBadClass[componentName]) { + 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 + ); - if (typeof getDerivedStateFromProps === "function") { - applyDerivedStateFromProps( - workInProgress, - ctor, - getDerivedStateFromProps, - newProps - ); - newState = workInProgress.memoizedState; - } + didWarnAboutBadClass[componentName] = true; + } + } - 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, - // both before and after `shouldComponentUpdate` has been called. Not ideal, - // but I'm loath to refactor this function. This only happens for memoized - // components so it's not that common. - (enableLazyContextPropagation && - current !== null && - current.dependencies !== null && - checkIfContextChanged(current.dependencies)); - - if (shouldUpdate) { - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for components using the new APIs. - if ( - !hasNewLifecycles && - (typeof instance.UNSAFE_componentWillUpdate === "function" || - typeof instance.componentWillUpdate === "function") - ) { - if (typeof instance.componentWillUpdate === "function") { - instance.componentWillUpdate(newProps, newState, nextContext); - } + if (workInProgress.mode & StrictLegacyMode) { + ReactStrictModeWarnings.recordLegacyContextWarning( + workInProgress, + null + ); + } - if (typeof instance.UNSAFE_componentWillUpdate === "function") { - instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext); + setIsRendering(true); + ReactCurrentOwner$1.current = workInProgress; + value = renderWithHooks( + null, + workInProgress, + Component, + props, + context, + renderLanes + ); + setIsRendering(false); } - } - if (typeof instance.componentDidUpdate === "function") { - workInProgress.flags |= Update; - } + if (enableSchedulingProfiler) { + markComponentRenderStopped(); + } // React DevTools reads this flag. - if (typeof instance.getSnapshotBeforeUpdate === "function") { - workInProgress.flags |= Snapshot; - } - } else { - // If an update was already in progress, we should schedule an Update - // effect even though we're bailing out, so that cWU/cDU are called. - if (typeof instance.componentDidUpdate === "function") { - if ( - unresolvedOldProps !== current.memoizedProps || - oldState !== current.memoizedState - ) { - workInProgress.flags |= Update; - } - } + workInProgress.flags |= PerformedWork; - if (typeof instance.getSnapshotBeforeUpdate === "function") { - if ( - unresolvedOldProps !== current.memoizedProps || - oldState !== current.memoizedState - ) { - workInProgress.flags |= Snapshot; + { + // Support for module components is deprecated and is removed behind a flag. + // Whether or not it would crash later, we want to show a good message in DEV first. + if ( + typeof value === "object" && + value !== null && + typeof value.render === "function" && + value.$$typeof === undefined + ) { + var _componentName = getComponentNameFromType(Component) || "Unknown"; + + if (!didWarnAboutModulePatternComponent[_componentName]) { + 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 + ); + + didWarnAboutModulePatternComponent[_componentName] = true; + } + } } - } // If shouldComponentUpdate returned false, we should still update the - // memoized props/state to indicate that this work can be reused. - workInProgress.memoizedProps = newProps; - workInProgress.memoizedState = newState; - } // Update the existing instance's state, props, and context pointers even - // if shouldComponentUpdate returns false. + { + // Proceed under the assumption that this is a function component + workInProgress.tag = FunctionComponent; + + { + if (Component.contextTypes) { + error( + "%s uses the legacy contextTypes API which is no longer supported. " + + "Use React.createContext() with React.useContext() instead.", + getComponentNameFromType(Component) || "Unknown" + ); + } + } - instance.props = newProps; - instance.state = newState; - instance.context = nextContext; - return shouldUpdate; -} + reconcileChildren(null, workInProgress, value, renderLanes); -function createCapturedValueAtFiber(value, source) { - // If the value is an error, call this function immediately after it is thrown - // so the stack is accurate. - return { - value: value, - source: source, - stack: getStackByFiberInDevAndProd(source), - digest: null - }; -} -function createCapturedValue(value, digest, stack) { - return { - value: value, - source: null, - stack: stack != null ? stack : null, - digest: digest != null ? digest : null - }; -} + { + validateFunctionComponentInDev(workInProgress, Component); + } -var ReactFiberErrorDialogWWW = require("ReactFiberErrorDialog"); + return workInProgress.child; + } + } -if (typeof ReactFiberErrorDialogWWW.showErrorDialog !== "function") { - throw new Error( - "Expected ReactFiberErrorDialog.showErrorDialog to be a function." - ); -} + function validateFunctionComponentInDev(workInProgress, Component) { + { + if (Component) { + if (Component.childContextTypes) { + error( + "%s(...): childContextTypes cannot be defined on a function component.", + Component.displayName || Component.name || "Component" + ); + } + } -function showErrorDialog(boundary, errorInfo) { - var capturedError = { - componentStack: errorInfo.stack !== null ? errorInfo.stack : "", - error: errorInfo.value, - errorBoundary: - boundary !== null && boundary.tag === ClassComponent - ? boundary.stateNode - : null - }; - return ReactFiberErrorDialogWWW.showErrorDialog(capturedError); -} + if (workInProgress.ref !== null) { + var info = ""; + var ownerName = getCurrentFiberOwnerNameInDevOrNull(); -function logCapturedError(boundary, errorInfo) { - try { - var logError = showErrorDialog(boundary, errorInfo); // Allow injected showErrorDialog() to prevent default console.error logging. - // This enables renderers like ReactNative to better manage redbox behavior. + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; + } - if (logError === false) { - return; - } + var warningKey = ownerName || ""; + var debugSource = workInProgress._debugSource; - var error = errorInfo.value; + if (debugSource) { + warningKey = debugSource.fileName + ":" + debugSource.lineNumber; + } - if (true) { - var source = errorInfo.source; - var stack = errorInfo.stack; - var componentStack = stack !== null ? stack : ""; // Browsers support silencing uncaught errors by calling - // `preventDefault()` in window `error` handler. - // We record this information as an expando on the error. + if (!didWarnAboutFunctionRefs[warningKey]) { + didWarnAboutFunctionRefs[warningKey] = true; - if (error != null && error._suppressLogging) { - if (boundary.tag === ClassComponent) { - // The error is recoverable and was silenced. - // Ignore it and don't print the stack addendum. - // This is handy for testing error boundaries without noise. - return; - } // The error is fatal. Since the silencing might have - // been accidental, we'll surface it anyway. - // However, the browser would have silenced the original error - // so we'll print it first, and then print the stack addendum. - - console["error"](error); // Don't transform to our wrapper - // For a more detailed description of this block, see: - // https://github.com/facebook/react/pull/13384 - } - - var componentName = source ? getComponentNameFromFiber(source) : null; - var componentNameMessage = componentName - ? "The above error occurred in the <" + componentName + "> component:" - : "The above error occurred in one of your React components:"; - var errorBoundaryMessage; - - if (boundary.tag === HostRoot) { - 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."; - } else { - var errorBoundaryName = - getComponentNameFromFiber(boundary) || "Anonymous"; - errorBoundaryMessage = - "React will try to recreate this component tree from scratch " + - ("using the error boundary you provided, " + errorBoundaryName + "."); - } - - var combinedMessage = - componentNameMessage + - "\n" + - componentStack + - "\n\n" + - ("" + errorBoundaryMessage); // In development, we provide our own message with just the component stack. - // We don't include the original error message and JS stack because the browser - // has already printed it. Even if the application swallows the error, it is still - // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils. - - console["error"](combinedMessage); // Don't transform to our wrapper - } - } catch (e) { - // This method must not throw, or React internal state will get messed up. - // If console.error is overridden, or logCapturedError() shows a dialog that throws, - // we want to report this error outside of the normal stack as a last resort. - // https://github.com/facebook/react/issues/13188 - setTimeout(function () { - throw e; - }); - } -} + error( + "Function components cannot be given refs. " + + "Attempts to access this ref will fail. " + + "Did you mean to use React.forwardRef()?%s", + info + ); + } + } -function createRootErrorUpdate(fiber, errorInfo, lane) { - var update = createUpdate(lane); // Unmount the root by rendering null. + if (Component.defaultProps !== undefined) { + var componentName = getComponentNameFromType(Component) || "Unknown"; - update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property - // being called "element". + if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) { + error( + "%s: Support for defaultProps will be removed from function components " + + "in a future major release. Use JavaScript default parameters instead.", + componentName + ); - update.payload = { - element: null - }; - var error = errorInfo.value; + didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true; + } + } - update.callback = function () { - onUncaughtError(error); - logCapturedError(fiber, errorInfo); - }; + if (typeof Component.getDerivedStateFromProps === "function") { + var _componentName3 = + getComponentNameFromType(Component) || "Unknown"; - return update; -} + if ( + !didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] + ) { + error( + "%s: Function components do not support getDerivedStateFromProps.", + _componentName3 + ); -function createClassErrorUpdate(fiber, errorInfo, lane) { - var update = createUpdate(lane); - update.tag = CaptureUpdate; - var getDerivedStateFromError = fiber.type.getDerivedStateFromError; + didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = + true; + } + } - if (typeof getDerivedStateFromError === "function") { - var error$1 = errorInfo.value; + if ( + typeof Component.contextType === "object" && + Component.contextType !== null + ) { + var _componentName4 = + getComponentNameFromType(Component) || "Unknown"; - update.payload = function () { - return getDerivedStateFromError(error$1); - }; + if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { + error( + "%s: Function components do not support contextType.", + _componentName4 + ); - update.callback = function () { - { - markFailedErrorBoundaryForHotReloading(fiber); + didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; + } + } } + } - logCapturedError(fiber, errorInfo); + var SUSPENDED_MARKER = { + dehydrated: null, + treeContext: null, + retryLane: NoLane }; - } - var inst = fiber.stateNode; - - if (inst !== null && typeof inst.componentDidCatch === "function") { - // $FlowFixMe[missing-this-annot] - update.callback = function callback() { - { - markFailedErrorBoundaryForHotReloading(fiber); - } + function mountSuspenseOffscreenState(renderLanes) { + return { + baseLanes: renderLanes, + cachePool: getSuspendedCache() + }; + } - logCapturedError(fiber, errorInfo); + function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { + var cachePool = null; - if (typeof getDerivedStateFromError !== "function") { - // To preserve the preexisting retry behavior of error boundaries, - // we keep track of which ones already failed during this batch. - // This gets reset before we yield back to the browser. - // TODO: Warn in strict mode if getDerivedStateFromError is - // not defined. - markLegacyErrorBoundaryAsFailed(this); - } + { + var prevCachePool = prevOffscreenState.cachePool; - var error$1 = errorInfo.value; - var stack = errorInfo.stack; - this.componentDidCatch(error$1, { - componentStack: stack !== null ? stack : "" - }); + if (prevCachePool !== null) { + var parentCache = CacheContext._currentValue2; - { - if (typeof getDerivedStateFromError !== "function") { - // If componentDidCatch is the only error boundary method defined, - // then it needs to call setState to recover from errors. - // If no state update is scheduled then the boundary will swallow the error. - if (!includesSomeLane(fiber.lanes, SyncLane)) { - 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" - ); + if (prevCachePool.parent !== parentCache) { + // Detected a refresh in the parent. This overrides any previously + // suspended cache. + cachePool = { + parent: parentCache, + pool: parentCache + }; + } else { + // We can reuse the cache from last time. The only thing that would have + // overridden it is a parent refresh, which we checked for above. + cachePool = prevCachePool; } + } else { + // If there's no previous cache pool, grab the current one. + cachePool = getSuspendedCache(); } } - }; - } - return update; -} + return { + baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), + cachePool: cachePool + }; + } // TODO: Probably should inline this back + + function shouldRemainOnFallback(current, workInProgress, renderLanes) { + // If we're already showing a fallback, there are cases where we need to + // remain on that fallback regardless of whether the content has resolved. + // For example, SuspenseList coordinates when nested content appears. + // TODO: For compatibility with offscreen prerendering, this should also check + // whether the current fiber (if it exists) was visible in the previous tree. + if (current !== null) { + var suspenseState = current.memoizedState; -function resetSuspendedComponent(sourceFiber, rootRenderLanes) { - if (enableLazyContextPropagation) { - var currentSourceFiber = sourceFiber.alternate; + if (suspenseState === null) { + // Currently showing content. Don't hide it, even if ForceSuspenseFallback + // is true. More precise name might be "ForceRemainSuspenseFallback". + // Note: This is a factoring smell. Can't remain on a fallback if there's + // no fallback to remain on. + return false; + } + } // Not currently showing content. Consult the Suspense context. - if (currentSourceFiber !== null) { - // Since we never visited the children of the suspended component, we - // need to propagate the context change now, to ensure that we visit - // them during the retry. - // - // We don't have to do this for errors because we retry errors without - // committing in between. So this is specific to Suspense. - propagateParentContextChangesToDeferredTree( - currentSourceFiber, - sourceFiber, - rootRenderLanes - ); + var suspenseContext = suspenseStackCursor.current; + return hasSuspenseListContext(suspenseContext, ForceSuspenseFallback); } - } // Reset the memoizedState to what it was before we attempted to render it. - // A legacy mode Suspense quirk, only relevant to hook components. - - var tag = sourceFiber.tag; - if ( - (sourceFiber.mode & ConcurrentMode) === NoMode && - (tag === FunctionComponent || - tag === ForwardRef || - tag === SimpleMemoComponent) - ) { - var currentSource = sourceFiber.alternate; - - if (currentSource) { - sourceFiber.updateQueue = currentSource.updateQueue; - sourceFiber.memoizedState = currentSource.memoizedState; - sourceFiber.lanes = currentSource.lanes; - } else { - sourceFiber.updateQueue = null; - sourceFiber.memoizedState = null; + function getRemainingWorkInPrimaryTree(current, renderLanes) { + // TODO: Should not remove render lanes that were pinged during this render + return removeLanes(current.childLanes, renderLanes); } - } -} - -function markSuspenseBoundaryShouldCapture( - suspenseBoundary, - returnFiber, - sourceFiber, - root, - rootRenderLanes -) { - // This marks a Suspense boundary so that when we're unwinding the stack, - // it captures the suspended "exception" and does a second (fallback) pass. - if ((suspenseBoundary.mode & ConcurrentMode) === NoMode) { - // Legacy Mode Suspense - // - // If the boundary is in legacy mode, we should *not* - // suspend the commit. Pretend as if the suspended component rendered - // null and keep rendering. When the Suspense boundary completes, - // we'll do a second pass to render the fallback. - if (suspenseBoundary === returnFiber) { - // Special case where we suspended while reconciling the children of - // a Suspense boundary's inner Offscreen wrapper fiber. This happens - // when a React.lazy component is a direct child of a - // Suspense boundary. - // - // Suspense boundaries are implemented as multiple fibers, but they - // are a single conceptual unit. The legacy mode behavior where we - // pretend the suspended fiber committed as `null` won't work, - // because in this case the "suspended" fiber is the inner - // Offscreen wrapper. - // - // Because the contents of the boundary haven't started rendering - // yet (i.e. nothing in the tree has partially rendered) we can - // switch to the regular, concurrent mode behavior: mark the - // boundary with ShouldCapture and enter the unwind phase. - suspenseBoundary.flags |= ShouldCapture; - } else { - suspenseBoundary.flags |= DidCapture; - sourceFiber.flags |= ForceUpdateForLegacySuspense; // We're going to commit this fiber even though it didn't complete. - // But we shouldn't call any lifecycle methods or callbacks. Remove - // all lifecycle effect tags. - - sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete); - - if (sourceFiber.tag === ClassComponent) { - var currentSourceFiber = sourceFiber.alternate; - - if (currentSourceFiber === null) { - // This is a new mount. Change the tag so it's not mistaken for a - // completed class component. For example, we should not call - // componentWillUnmount if it is deleted. - sourceFiber.tag = IncompleteClassComponent; - } else { - // When we try rendering again, we should not reuse the current fiber, - // since it's known to be in an inconsistent state. Use a force update to - // prevent a bail out. - var update = createUpdate(SyncLane); - update.tag = ForceUpdate; - enqueueUpdate(sourceFiber, update, SyncLane); - } - } // The source fiber did not complete. Mark it with Sync priority to - // indicate that it still has pending work. - - sourceFiber.lanes = mergeLanes(sourceFiber.lanes, SyncLane); - } - - return suspenseBoundary; - } // Confirmed that the boundary is in a concurrent mode tree. Continue - // with the normal suspend path. - // - // After this we'll use a set of heuristics to determine whether this - // render pass will run to completion or restart or "suspend" the commit. - // The actual logic for this is spread out in different places. - // - // This first principle is that if we're going to suspend when we complete - // a root, then we should also restart if we get an update or ping that - // might unsuspend it, and vice versa. The only reason to suspend is - // because you think you might want to restart before committing. However, - // it doesn't make sense to restart only while in the period we're suspended. - // - // Restarting too aggressively is also not good because it starves out any - // intermediate loading state. So we use heuristics to determine when. - // Suspense Heuristics - // - // If nothing threw a Promise or all the same fallbacks are already showing, - // then don't suspend/restart. - // - // If this is an initial render of a new tree of Suspense boundaries and - // those trigger a fallback, then don't suspend/restart. We want to ensure - // that we can show the initial loading state as quickly as possible. - // - // If we hit a "Delayed" case, such as when we'd switch from content back into - // a fallback, then we should always suspend/restart. Transitions apply - // to this case. If none is defined, JND is used instead. - // - // If we're already showing a fallback and it gets "retried", allowing us to show - // another level, but there's still an inner boundary that would show a fallback, - // then we suspend/restart for 500ms since the last time we showed a fallback - // anywhere in the tree. This effectively throttles progressive loading into a - // consistent train of commits. This also gives us an opportunity to restart to - // get to the completed state slightly earlier. - // - // If there's ambiguity due to batching it's resolved in preference of: - // 1) "delayed", 2) "initial render", 3) "retry". - // - // We want to ensure that a "busy" state doesn't get force committed. We want to - // ensure that new initial loading states can commit as soon as possible. - - suspenseBoundary.flags |= ShouldCapture; // TODO: I think we can remove this, since we now use `DidCapture` in - // the begin phase to prevent an early bailout. - - suspenseBoundary.lanes = rootRenderLanes; - return suspenseBoundary; -} -function throwException( - root, - returnFiber, - sourceFiber, - value, - rootRenderLanes -) { - // The source fiber did not complete. - sourceFiber.flags |= Incomplete; - - { - if (isDevToolsPresent) { - // If we have pending work still, restore the original updaters - restorePendingUpdaters(root, rootRenderLanes); - } - } - - if (value !== null && typeof value === "object") { - if (typeof value.then === "function") { - // This is a wakeable. The component suspended. - var wakeable = value; - resetSuspendedComponent(sourceFiber, rootRenderLanes); + function updateSuspenseComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend. { - if (enableDebugTracing) { - if (sourceFiber.mode & DebugTracingMode) { - var name = getComponentNameFromFiber(sourceFiber) || "Unknown"; - logComponentSuspended(name, wakeable); - } - } - } // Mark the nearest Suspense boundary to switch to rendering a fallback. - - var suspenseBoundary = getSuspenseHandler(); - - if (suspenseBoundary !== null) { - switch (suspenseBoundary.tag) { - case SuspenseComponent: { - // If this suspense boundary is not already showing a fallback, mark - // the in-progress render as suspended. We try to perform this logic - // as soon as soon as possible during the render phase, so the work - // loop can know things like whether it's OK to switch to other tasks, - // or whether it can wait for data to resolve before continuing. - // TODO: Most of these checks are already performed when entering a - // Suspense boundary. We should track the information on the stack so - // we don't have to recompute it on demand. This would also allow us - // to unify with `use` which needs to perform this logic even sooner, - // before `throwException` is called. - if (sourceFiber.mode & ConcurrentMode) { - if (getShellBoundary() === null) { - // Suspended in the "shell" of the app. This is an undesirable - // loading state. We should avoid committing this tree. - renderDidSuspendDelayIfPossible(); - } else { - // If we suspended deeper than the shell, we don't need to delay - // the commmit. However, we still call renderDidSuspend if this is - // a new boundary, to tell the work loop that a new fallback has - // appeared during this render. - // TODO: Theoretically we should be able to delete this branch. - // It's currently used for two things: 1) to throttle the - // appearance of successive loading states, and 2) in - // SuspenseList, to determine whether the children include any - // pending fallbacks. For 1, we should apply throttling to all - // retries, not just ones that render an additional fallback. For - // 2, we should check subtreeFlags instead. Then we can delete - // this branch. - var current = suspenseBoundary.alternate; - - if (current === null) { - renderDidSuspend(); - } - } - } + if (shouldSuspend(workInProgress)) { + workInProgress.flags |= DidCapture; + } + } - suspenseBoundary.flags &= ~ForceClientRender; - markSuspenseBoundaryShouldCapture( - suspenseBoundary, - returnFiber, - sourceFiber, - root, - rootRenderLanes - ); // Retry listener - // - // If the fallback does commit, we need to attach a different type of - // listener. This one schedules an update on the Suspense boundary to - // turn the fallback state off. - // - // Stash the wakeable on the boundary fiber so we can access it in the - // commit phase. - // - // When the wakeable resolves, we'll attempt to render the boundary - // again ("retry"). - // Check if this is a Suspensey resource. We do not attach retry - // listeners to these, because we don't actually need them for - // rendering. Only for committing. Instead, if a fallback commits - // and the only thing that suspended was a Suspensey resource, we - // retry immediately. - // TODO: Refactor throwException so that we don't have to do this type - // check. The caller already knows what the cause was. - - var isSuspenseyResource = wakeable === noopSuspenseyCommitThenable; - - if (isSuspenseyResource) { - suspenseBoundary.flags |= ScheduleRetry; - } else { - var retryQueue = suspenseBoundary.updateQueue; + var showFallback = false; + var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags$1; - if (retryQueue === null) { - suspenseBoundary.updateQueue = new Set([wakeable]); + if (didSuspend || shouldRemainOnFallback(current)) { + // Something in this boundary's subtree already suspended. Switch to + // rendering the fallback children. + showFallback = true; + workInProgress.flags &= ~DidCapture; + } // OK, the next part is confusing. We're about to reconcile the Suspense + // boundary's children. This involves some custom reconciliation logic. Two + // main reasons this is so complicated. + // + // First, Legacy Mode has different semantics for backwards compatibility. The + // primary tree will commit in an inconsistent state, so when we do the + // second pass to render the fallback, we do some exceedingly, uh, clever + // hacks to make that not totally break. Like transferring effects and + // deletions from hidden tree. In Concurrent Mode, it's much simpler, + // because we bailout on the primary tree completely and leave it in its old + // state, no effects. Same as what we do for Offscreen (except that + // Offscreen doesn't have the first render pass). + // + // Second is hydration. During hydration, the Suspense fiber has a slightly + // different layout, where the child points to a dehydrated fragment, which + // contains the DOM rendered by the server. + // + // Third, even if you set all that aside, Suspense is like error boundaries in + // that we first we try to render one tree, and if that fails, we render again + // and switch to a different tree. Like a try/catch block. So we have to track + // which branch we're currently rendering. Ideally we would model this using + // a stack. + + if (current === null) { + var nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; + + if (showFallback) { + pushFallbackTreeSuspenseHandler(workInProgress); + var fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); + var primaryChildFragment = workInProgress.child; + primaryChildFragment.memoizedState = + mountSuspenseOffscreenState(renderLanes); + workInProgress.memoizedState = SUSPENDED_MARKER; + + if (enableTransitionTracing) { + var currentTransitions = getPendingTransitions(); + + if (currentTransitions !== null) { + var parentMarkerInstances = getMarkerInstances(); + var offscreenQueue = primaryChildFragment.updateQueue; + + if (offscreenQueue === null) { + var newOffscreenQueue = { + transitions: currentTransitions, + markerInstances: parentMarkerInstances, + retryQueue: null + }; + primaryChildFragment.updateQueue = newOffscreenQueue; } else { - retryQueue.add(wakeable); - } // We only attach ping listeners in concurrent mode. Legacy - // Suspense always commits fallbacks synchronously, so there are - // no pings. - - if (suspenseBoundary.mode & ConcurrentMode) { - attachPingListener(root, wakeable, rootRenderLanes); + offscreenQueue.transitions = currentTransitions; + offscreenQueue.markerInstances = parentMarkerInstances; } } - - return; } - case OffscreenComponent: { - if (suspenseBoundary.mode & ConcurrentMode) { - suspenseBoundary.flags |= ShouldCapture; + return fallbackFragment; + } else if (typeof nextProps.unstable_expectedLoadTime === "number") { + // This is a CPU-bound tree. Skip this tree and show a placeholder to + // unblock the surrounding content. Then immediately retry after the + // initial commit. + pushFallbackTreeSuspenseHandler(workInProgress); - var _isSuspenseyResource = - wakeable === noopSuspenseyCommitThenable; + var _fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); - if (_isSuspenseyResource) { - suspenseBoundary.flags |= ScheduleRetry; - } else { - var offscreenQueue = suspenseBoundary.updateQueue; - - if (offscreenQueue === null) { - var newOffscreenQueue = { - transitions: null, - markerInstances: null, - retryQueue: new Set([wakeable]) - }; - suspenseBoundary.updateQueue = newOffscreenQueue; - } else { - var _retryQueue = offscreenQueue.retryQueue; + var _primaryChildFragment = workInProgress.child; + _primaryChildFragment.memoizedState = + mountSuspenseOffscreenState(renderLanes); + workInProgress.memoizedState = SUSPENDED_MARKER; // TODO: Transition Tracing is not yet implemented for CPU Suspense. + // Since nothing actually suspended, there will nothing to ping this to + // get it started back up to attempt the next item. While in terms of + // priority this work has the same priority as this current render, it's + // not part of the same transition once the transition has committed. If + // it's sync, we still want to yield so that it can be painted. + // Conceptually, this is really the same as pinging. We can use any + // RetryLane even if it's the one currently rendering since we're leaving + // it behind on this node. + + workInProgress.lanes = SomeRetryLane; + return _fallbackFragment; + } else { + pushPrimaryTreeSuspenseHandler(workInProgress); + return mountSuspensePrimaryChildren( + workInProgress, + nextPrimaryChildren + ); + } + } else { + // This is an update. + // Special path for hydration + var prevState = current.memoizedState; - if (_retryQueue === null) { - offscreenQueue.retryQueue = new Set([wakeable]); - } else { - _retryQueue.add(wakeable); - } - } + if (prevState !== null) { + var _dehydrated = prevState.dehydrated; + + if (_dehydrated !== null) { + return updateDehydratedSuspenseComponent( + current, + workInProgress, + didSuspend, + nextProps, + _dehydrated, + prevState, + renderLanes + ); + } + } - attachPingListener(root, wakeable, rootRenderLanes); + if (showFallback) { + pushFallbackTreeSuspenseHandler(workInProgress); + var _nextFallbackChildren = nextProps.fallback; + var _nextPrimaryChildren = nextProps.children; + var fallbackChildFragment = updateSuspenseFallbackChildren( + current, + workInProgress, + _nextPrimaryChildren, + _nextFallbackChildren, + renderLanes + ); + var _primaryChildFragment2 = workInProgress.child; + var prevOffscreenState = current.child.memoizedState; + _primaryChildFragment2.memoizedState = + prevOffscreenState === null + ? mountSuspenseOffscreenState(renderLanes) + : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); + + if (enableTransitionTracing) { + var _currentTransitions = getPendingTransitions(); + + if (_currentTransitions !== null) { + var _parentMarkerInstances = getMarkerInstances(); + + var _offscreenQueue = _primaryChildFragment2.updateQueue; + var currentOffscreenQueue = current.updateQueue; + + if (_offscreenQueue === null) { + var _newOffscreenQueue = { + transitions: _currentTransitions, + markerInstances: _parentMarkerInstances, + retryQueue: null + }; + _primaryChildFragment2.updateQueue = _newOffscreenQueue; + } else if (_offscreenQueue === currentOffscreenQueue) { + // If the work-in-progress queue is the same object as current, we + // can't modify it without cloning it first. + var _newOffscreenQueue2 = { + transitions: _currentTransitions, + markerInstances: _parentMarkerInstances, + retryQueue: + currentOffscreenQueue !== null + ? currentOffscreenQueue.retryQueue + : null + }; + _primaryChildFragment2.updateQueue = _newOffscreenQueue2; + } else { + _offscreenQueue.transitions = _currentTransitions; + _offscreenQueue.markerInstances = _parentMarkerInstances; } - - return; } } - } - throw new Error( - "Unexpected Suspense handler tag (" + - suspenseBoundary.tag + - "). This " + - "is a bug in React." - ); - } else { - // No boundary was found. Unless this is a sync update, this is OK. - // We can suspend and wait for more data to arrive. - if (root.tag === ConcurrentRoot) { - // In a concurrent root, suspending without a Suspense boundary is - // allowed. It will suspend indefinitely without committing. - // - // TODO: Should we have different behavior for discrete updates? What - // about flushSync? Maybe it should put the tree into an inert state, - // and potentially log a warning. Revisit this for a future release. - attachPingListener(root, wakeable, rootRenderLanes); - renderDidSuspendDelayIfPossible(); - return; + _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree( + current, + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + return fallbackChildFragment; } else { - // In a legacy root, suspending without a boundary is always an error. - 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." + pushPrimaryTreeSuspenseHandler(workInProgress); + var _nextPrimaryChildren2 = nextProps.children; + + var _primaryChildFragment3 = updateSuspensePrimaryChildren( + current, + workInProgress, + _nextPrimaryChildren2, + renderLanes ); - value = uncaughtSuspenseError; + + workInProgress.memoizedState = null; + return _primaryChildFragment3; } } } - } // This is a regular error, not a Suspense wakeable. - value = createCapturedValueAtFiber(value, sourceFiber); - renderDidError(value); // We didn't find a boundary that could handle this type of exception. Start - // over and traverse parent path again, this time treating the exception - // as an error. + function mountSuspensePrimaryChildren( + workInProgress, + primaryChildren, + renderLanes + ) { + var mode = workInProgress.mode; + var primaryChildProps = { + mode: "visible", + children: primaryChildren + }; + var primaryChildFragment = mountWorkInProgressOffscreenFiber( + primaryChildProps, + mode + ); + primaryChildFragment.return = workInProgress; + workInProgress.child = primaryChildFragment; + return primaryChildFragment; + } - var workInProgress = returnFiber; + function mountSuspenseFallbackChildren( + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes + ) { + var mode = workInProgress.mode; + var progressedPrimaryFragment = workInProgress.child; + var primaryChildProps = { + mode: "hidden", + children: primaryChildren + }; + var primaryChildFragment; + var fallbackChildFragment; - do { - switch (workInProgress.tag) { - case HostRoot: { - var _errorInfo = value; - workInProgress.flags |= ShouldCapture; - var lane = pickArbitraryLane(rootRenderLanes); - workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); - var update = createRootErrorUpdate(workInProgress, _errorInfo, lane); - enqueueCapturedUpdate(workInProgress, update); - return; + if ( + (mode & ConcurrentMode) === NoMode && + progressedPrimaryFragment !== null + ) { + // In legacy mode, we commit the primary tree as if it successfully + // completed, even though it's in an inconsistent state. + primaryChildFragment = progressedPrimaryFragment; + primaryChildFragment.childLanes = NoLanes; + primaryChildFragment.pendingProps = primaryChildProps; + + if (workInProgress.mode & ProfileMode) { + // Reset the durations from the first pass so they aren't included in the + // final amounts. This seems counterintuitive, since we're intentionally + // not measuring part of the render phase, but this makes it match what we + // do in Concurrent Mode. + primaryChildFragment.actualDuration = 0; + primaryChildFragment.actualStartTime = -1; + primaryChildFragment.selfBaseDuration = 0; + primaryChildFragment.treeBaseDuration = 0; + } + + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + } else { + primaryChildFragment = mountWorkInProgressOffscreenFiber( + primaryChildProps, + mode + ); + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); } - case ClassComponent: - // Capture and retry - var errorInfo = value; - var ctor = workInProgress.type; - var instance = workInProgress.stateNode; - - if ( - (workInProgress.flags & DidCapture) === NoFlags$1 && - (typeof ctor.getDerivedStateFromError === "function" || - (instance !== null && - typeof instance.componentDidCatch === "function" && - !isAlreadyFailedLegacyErrorBoundary(instance))) - ) { - workInProgress.flags |= ShouldCapture; - - var _lane = pickArbitraryLane(rootRenderLanes); + primaryChildFragment.return = workInProgress; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; + } - workInProgress.lanes = mergeLanes(workInProgress.lanes, _lane); // Schedule the error boundary to re-render using updated state + function mountWorkInProgressOffscreenFiber( + offscreenProps, + mode, + renderLanes + ) { + // The props argument to `createFiberFromOffscreen` is `any` typed, so we use + // this wrapper function to constrain it. + return createFiberFromOffscreen(offscreenProps, mode, NoLanes, null); + } - var _update = createClassErrorUpdate( - workInProgress, - errorInfo, - _lane - ); + function updateWorkInProgressOffscreenFiber(current, offscreenProps) { + // The props argument to `createWorkInProgress` is `any` typed, so we use this + // wrapper function to constrain it. + return createWorkInProgress(current, offscreenProps); + } - enqueueCapturedUpdate(workInProgress, _update); - return; + function updateSuspensePrimaryChildren( + current, + workInProgress, + primaryChildren, + renderLanes + ) { + var currentPrimaryChildFragment = current.child; + var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; + var primaryChildFragment = updateWorkInProgressOffscreenFiber( + currentPrimaryChildFragment, + { + mode: "visible", + children: primaryChildren } + ); - break; - } // $FlowFixMe[incompatible-type] we bail out when we get a null - - workInProgress = workInProgress.return; - } while (workInProgress !== null); -} - -var TransitionRoot = 0; -var TransitionTracingMarker = 1; -function processTransitionCallbacks(pendingTransitions, endTime, callbacks) { - if (enableTransitionTracing) { - if (pendingTransitions !== null) { - var transitionStart = pendingTransitions.transitionStart; - var onTransitionStart = callbacks.onTransitionStart; - - if (transitionStart !== null && onTransitionStart != null) { - transitionStart.forEach(function (transition) { - return onTransitionStart(transition.name, transition.startTime); - }); + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + primaryChildFragment.lanes = renderLanes; } - var markerProgress = pendingTransitions.markerProgress; - var onMarkerProgress = callbacks.onMarkerProgress; - - if (onMarkerProgress != null && markerProgress !== null) { - markerProgress.forEach(function (markerInstance, markerName) { - if (markerInstance.transitions !== null) { - // TODO: Clone the suspense object so users can't modify it - var pending = - markerInstance.pendingBoundaries !== null - ? Array.from(markerInstance.pendingBoundaries.values()) - : []; - markerInstance.transitions.forEach(function (transition) { - onMarkerProgress( - transition.name, - markerName, - transition.startTime, - endTime, - pending - ); - }); - } - }); - } + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = null; - var markerComplete = pendingTransitions.markerComplete; - var onMarkerComplete = callbacks.onMarkerComplete; + if (currentFallbackChildFragment !== null) { + // Delete the fallback child fragment + var deletions = workInProgress.deletions; - if (markerComplete !== null && onMarkerComplete != null) { - markerComplete.forEach(function (transitions, markerName) { - transitions.forEach(function (transition) { - onMarkerComplete( - transition.name, - markerName, - transition.startTime, - endTime - ); - }); - }); + if (deletions === null) { + workInProgress.deletions = [currentFallbackChildFragment]; + workInProgress.flags |= ChildDeletion; + } else { + deletions.push(currentFallbackChildFragment); + } } - var markerIncomplete = pendingTransitions.markerIncomplete; - var onMarkerIncomplete = callbacks.onMarkerIncomplete; + workInProgress.child = primaryChildFragment; + return primaryChildFragment; + } - if (onMarkerIncomplete != null && markerIncomplete !== null) { - markerIncomplete.forEach(function (_ref, markerName) { - var transitions = _ref.transitions, - aborts = _ref.aborts; - transitions.forEach(function (transition) { - var filteredAborts = []; - aborts.forEach(function (abort) { - switch (abort.reason) { - case "marker": { - filteredAborts.push({ - type: "marker", - name: abort.name, - endTime: endTime - }); - break; - } + function updateSuspenseFallbackChildren( + current, + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes + ) { + var mode = workInProgress.mode; + var currentPrimaryChildFragment = current.child; + var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; + var primaryChildProps = { + mode: "hidden", + children: primaryChildren + }; + var primaryChildFragment; - case "suspense": { - filteredAborts.push({ - type: "suspense", - name: abort.name, - endTime: endTime - }); - break; - } - } - }); + if ( + // In legacy mode, we commit the primary tree as if it successfully + // completed, even though it's in an inconsistent state. + (mode & ConcurrentMode) === NoMode && // Make sure we're on the second pass, i.e. the primary child fragment was + // already cloned. In legacy mode, the only case where this isn't true is + // when DevTools forces us to display a fallback; we skip the first render + // pass entirely and go straight to rendering the fallback. (In Concurrent + // Mode, SuspenseList can also trigger this scenario, but this is a legacy- + // only codepath.) + workInProgress.child !== currentPrimaryChildFragment + ) { + var progressedPrimaryFragment = workInProgress.child; + primaryChildFragment = progressedPrimaryFragment; + primaryChildFragment.childLanes = NoLanes; + primaryChildFragment.pendingProps = primaryChildProps; + + if (workInProgress.mode & ProfileMode) { + // Reset the durations from the first pass so they aren't included in the + // final amounts. This seems counterintuitive, since we're intentionally + // not measuring part of the render phase, but this makes it match what we + // do in Concurrent Mode. + primaryChildFragment.actualDuration = 0; + primaryChildFragment.actualStartTime = -1; + primaryChildFragment.selfBaseDuration = + currentPrimaryChildFragment.selfBaseDuration; + primaryChildFragment.treeBaseDuration = + currentPrimaryChildFragment.treeBaseDuration; + } // The fallback fiber was added as a deletion during the first pass. + // However, since we're going to remain on the fallback, we no longer want + // to delete it. + + workInProgress.deletions = null; + } else { + primaryChildFragment = updateWorkInProgressOffscreenFiber( + currentPrimaryChildFragment, + primaryChildProps + ); // Since we're reusing a current tree, we need to reuse the flags, too. + // (We don't do this in legacy mode, because in legacy mode we don't re-use + // the current tree; see previous branch.) - if (filteredAborts.length > 0) { - onMarkerIncomplete( - transition.name, - markerName, - transition.startTime, - filteredAborts - ); - } - }); - }); + primaryChildFragment.subtreeFlags = + currentPrimaryChildFragment.subtreeFlags & StaticMask; } - var transitionProgress = pendingTransitions.transitionProgress; - var onTransitionProgress = callbacks.onTransitionProgress; - - if (onTransitionProgress != null && transitionProgress !== null) { - transitionProgress.forEach(function (pending, transition) { - onTransitionProgress( - transition.name, - transition.startTime, - endTime, - Array.from(pending.values()) - ); - }); - } + var fallbackChildFragment; - var transitionComplete = pendingTransitions.transitionComplete; - var onTransitionComplete = callbacks.onTransitionComplete; + if (currentFallbackChildFragment !== null) { + fallbackChildFragment = createWorkInProgress( + currentFallbackChildFragment, + fallbackChildren + ); + } else { + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); // Needs a placement effect because the parent (the Suspense boundary) already + // mounted but this is a new fiber. - if (transitionComplete !== null && onTransitionComplete != null) { - transitionComplete.forEach(function (transition) { - return onTransitionComplete( - transition.name, - transition.startTime, - endTime - ); - }); + fallbackChildFragment.flags |= Placement; } - } - } -} // For every tracing marker, store a pointer to it. We will later access it -// to get the set of suspense boundaries that need to resolve before the -// tracing marker can be logged as complete -// This code lives separate from the ReactFiberTransition code because -// we push and pop on the tracing marker, not the suspense boundary - -var markerInstanceStack = createCursor(null); -function pushRootMarkerInstance(workInProgress) { - if (enableTransitionTracing) { - // On the root, every transition gets mapped to it's own map of - // suspense boundaries. The transition is marked as complete when - // the suspense boundaries map is empty. We do this because every - // transition completes at different times and depends on different - // suspense boundaries to complete. We store all the transitions - // along with its map of suspense boundaries in the root incomplete - // transitions map. Each entry in this map functions like a tracing - // marker does, so we can push it onto the marker instance stack - var transitions = getWorkInProgressTransitions(); - var root = workInProgress.stateNode; - - if (transitions !== null) { - transitions.forEach(function (transition) { - if (!root.incompleteTransitions.has(transition)) { - var markerInstance = { - tag: TransitionRoot, - transitions: new Set([transition]), - pendingBoundaries: null, - aborts: null, - name: null - }; - root.incompleteTransitions.set(transition, markerInstance); - } - }); + + fallbackChildFragment.return = workInProgress; + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; } - var markerInstances = []; // For ever transition on the suspense boundary, we push the transition - // along with its map of pending suspense boundaries onto the marker - // instance stack. + function retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + recoverableError + ) { + // Falling back to client rendering. Because this has performance + // implications, it's considered a recoverable error, even though the user + // likely won't observe anything wrong with the UI. + // + // The error is passed in as an argument to enforce that every caller provide + // a custom message, or explicitly opt out (currently the only path that opts + // out is legacy mode; every concurrent path provides an error). + if (recoverableError !== null) { + queueHydrationError(recoverableError); + } // This will add the old fiber to the deletion list - root.incompleteTransitions.forEach(function (markerInstance) { - markerInstances.push(markerInstance); - }); - push(markerInstanceStack, markerInstances, workInProgress); - } -} -function popRootMarkerInstance(workInProgress) { - if (enableTransitionTracing) { - pop(markerInstanceStack, workInProgress); - } -} -function pushMarkerInstance(workInProgress, markerInstance) { - if (enableTransitionTracing) { - if (markerInstanceStack.current === null) { - push(markerInstanceStack, [markerInstance], workInProgress); - } else { - push( - markerInstanceStack, - markerInstanceStack.current.concat(markerInstance), - workInProgress - ); - } - } -} -function popMarkerInstance(workInProgress) { - if (enableTransitionTracing) { - pop(markerInstanceStack, workInProgress); - } -} -function getMarkerInstances() { - if (enableTransitionTracing) { - return markerInstanceStack.current; - } + reconcileChildFibers(workInProgress, current.child, null, renderLanes); // We're now not suspended nor dehydrated. - return null; -} + var nextProps = workInProgress.pendingProps; + var primaryChildren = nextProps.children; + var primaryChildFragment = mountSuspensePrimaryChildren( + workInProgress, + primaryChildren + ); // Needs a placement effect because the parent (the Suspense boundary) already + // mounted but this is a new fiber. -var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; // A special exception that's used to unwind the stack when an update flows -// into a dehydrated boundary. - -var SelectiveHydrationException = new Error( - "This is not a real error. It's an implementation detail of React's " + - "selective hydration feature. If this leaks into userspace, it's a bug in " + - "React. Please file an issue." -); -var didReceiveUpdate = false; -var didWarnAboutBadClass; -var didWarnAboutModulePatternComponent; -var didWarnAboutContextTypeOnFunctionComponent; -var didWarnAboutGetDerivedStateOnFunctionComponent; -var didWarnAboutFunctionRefs; -var didWarnAboutReassigningProps; -var didWarnAboutRevealOrder; -var didWarnAboutTailOptions; -var didWarnAboutDefaultPropsOnFunctionComponent; - -{ - didWarnAboutBadClass = {}; - didWarnAboutModulePatternComponent = {}; - didWarnAboutContextTypeOnFunctionComponent = {}; - didWarnAboutGetDerivedStateOnFunctionComponent = {}; - didWarnAboutFunctionRefs = {}; - didWarnAboutReassigningProps = false; - didWarnAboutRevealOrder = {}; - didWarnAboutTailOptions = {}; - didWarnAboutDefaultPropsOnFunctionComponent = {}; -} + primaryChildFragment.flags |= Placement; + workInProgress.memoizedState = null; + return primaryChildFragment; + } -function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { - if (current === null) { - // If this is a fresh new component that hasn't been rendered yet, we - // won't update its child set by applying minimal side-effects. Instead, - // we will add them all to the child before it gets rendered. That means - // we can optimize this reconciliation pass by not tracking side-effects. - workInProgress.child = mountChildFibers( - workInProgress, - null, - nextChildren, - renderLanes - ); - } else { - // If the current child is the same as the work in progress, it means that - // we haven't yet started any work on these children. Therefore, we use - // the clone algorithm to create a copy of all the current children. - // If we had any progressed work already, that is invalid at this point so - // let's throw it out. - workInProgress.child = reconcileChildFibers( + function mountSuspenseFallbackAfterRetryWithoutHydrating( + current, workInProgress, - current.child, - nextChildren, + primaryChildren, + fallbackChildren, renderLanes - ); - } -} + ) { + var fiberMode = workInProgress.mode; + var primaryChildProps = { + mode: "visible", + children: primaryChildren + }; + var primaryChildFragment = mountWorkInProgressOffscreenFiber( + primaryChildProps, + fiberMode + ); + var fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + fiberMode, + renderLanes, + null + ); // Needs a placement effect because the parent (the Suspense + // boundary) already mounted but this is a new fiber. -function forceUnmountCurrentAndReconcile( - current, - workInProgress, - nextChildren, - renderLanes -) { - // This function is fork of reconcileChildren. It's used in cases where we - // want to reconcile without matching against the existing set. This has the - // effect of all current children being unmounted; even if the type and key - // are the same, the old child is unmounted and a new child is created. - // - // To do this, we're going to go through the reconcile algorithm twice. In - // the first pass, we schedule a deletion for all the current children by - // passing null. - workInProgress.child = reconcileChildFibers( - workInProgress, - current.child, - null, - renderLanes - ); // In the second pass, we mount the new children. The trick here is that we - // pass null in place of where we usually pass the current child set. This has - // the effect of remounting all children regardless of whether their - // identities match. - - workInProgress.child = reconcileChildFibers( - workInProgress, - null, - nextChildren, - renderLanes - ); -} + fallbackChildFragment.flags |= Placement; + primaryChildFragment.return = workInProgress; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; -function updateForwardRef( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - // TODO: current can be non-null here even if the component - // hasn't yet mounted. This happens after the first render suspends. - // We'll need to figure out if this is fine or can cause issues. - { - if (workInProgress.type !== workInProgress.elementType) { - // Lazy component props can't be validated in createElement - // because they're only guaranteed to be resolved here. - var innerPropTypes = Component.propTypes; - - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(Component) - ); + if ((workInProgress.mode & ConcurrentMode) !== NoMode) { + // We will have dropped the effect list which contains the + // deletion. We need to reconcile to delete the current child. + reconcileChildFibers(workInProgress, current.child, null, renderLanes); } - } - } - - var render = Component.render; - var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent - var nextChildren; - prepareToReadContext(workInProgress, renderLanes); - - if (enableSchedulingProfiler) { - markComponentRenderStarted(workInProgress); - } + return fallbackChildFragment; + } - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - nextChildren = renderWithHooks( + function updateDehydratedSuspenseComponent( current, workInProgress, - render, + didSuspend, nextProps, - ref, + suspenseInstance, + suspenseState, renderLanes - ); - setIsRendering(false); - } + ) { + if (!didSuspend) { + // This is the first render pass. Attempt to hydrate. + pushPrimaryTreeSuspenseHandler(workInProgress); // We should never be hydrating at this point because it is the first pass, - if (enableSchedulingProfiler) { - markComponentRenderStopped(); - } + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + null + ); + } - if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } + if (isSuspenseInstanceFallback()) { + // This boundary is in a permanent fallback state. In this case, we'll never + // get an update and we'll never be able to hydrate the final content. Let's just try the + // client side render instead. + var digest; + var message, stack; - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + { + var _getSuspenseInstanceF = + getSuspenseInstanceFallbackErrorDetails(); -function updateMemoComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - if (current === null) { - var type = Component.type; + digest = _getSuspenseInstanceF.digest; + message = _getSuspenseInstanceF.message; + stack = _getSuspenseInstanceF.stack; + } - if ( - isSimpleFunctionComponent(type) && - Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. - Component.defaultProps === undefined - ) { - var resolvedType = type; + var capturedValue = null; // TODO: Figure out a better signal than encoding a magic digest value. - { - resolvedType = resolveFunctionForHotReloading(type); - } // If this is a plain function component without default props, - // and with only the default shallow comparison, we upgrade it - // to a SimpleMemoComponent to allow fast path updates. + { + var error; - workInProgress.tag = SimpleMemoComponent; - workInProgress.type = resolvedType; + if (message) { + // eslint-disable-next-line react-internal/prod-error-codes + error = new Error(message); + } else { + error = new Error( + "The server could not finish this Suspense boundary, likely " + + "due to an error during server rendering. Switched to " + + "client rendering." + ); + } - { - validateFunctionComponentInDev(workInProgress, type); - } + error.digest = digest; + capturedValue = createCapturedValue(error, digest, stack); + } - return updateSimpleMemoComponent( - current, - workInProgress, - resolvedType, - nextProps, - renderLanes - ); - } + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + capturedValue + ); + } - { - var innerPropTypes = type.propTypes; - - if (innerPropTypes) { - // Inner memo component props aren't currently validated in createElement. - // We could move it there, but we'd still need this for lazy code path. - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(type) + if ( + enableLazyContextPropagation && // TODO: Factoring is a little weird, since we check this right below, too. + // But don't want to re-arrange the if-else chain until/unless this + // feature lands. + !didReceiveUpdate + ) { + // We need to check if any children have context before we decide to bail + // out, so propagate the changes now. + lazilyPropagateParentContextChanges( + current, + workInProgress, + renderLanes + ); + } // We use lanes to indicate that a child might depend on context, so if + // any context has changed, we need to treat is as if the input might have changed. + + var hasContextChanged = includesSomeLane( + renderLanes, + current.childLanes ); - } - if (Component.defaultProps !== undefined) { - var componentName = getComponentNameFromType(type) || "Unknown"; + if (didReceiveUpdate || hasContextChanged) { + // This boundary has changed since the first render. This means that we are now unable to + // hydrate it. We might still be able to hydrate it using a higher priority lane. + var root = getWorkInProgressRoot(); - if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) { - error( - "%s: Support for defaultProps will be removed from memo components " + - "in a future major release. Use JavaScript default parameters instead.", - componentName + if (root !== null) { + var attemptHydrationAtLane = getBumpedLaneForHydration( + root, + renderLanes + ); + + if ( + attemptHydrationAtLane !== NoLane && + attemptHydrationAtLane !== suspenseState.retryLane + ) { + // Intentionally mutating since this render will get interrupted. This + // is one of the very rare times where we mutate the current tree + // during the render phase. + suspenseState.retryLane = attemptHydrationAtLane; + enqueueConcurrentRenderForLane(current, attemptHydrationAtLane); + scheduleUpdateOnFiber(root, current, attemptHydrationAtLane); // Throw a special object that signals to the work loop that it should + // interrupt the current render. + // + // Because we're inside a React-only execution stack, we don't + // strictly need to throw here — we could instead modify some internal + // work loop state. But using an exception means we don't need to + // check for this case on every iteration of the work loop. So doing + // it this way moves the check out of the fast path. + + throw SelectiveHydrationException; + } + } // If we did not selectively hydrate, we'll continue rendering without + // hydrating. Mark this tree as suspended to prevent it from committing + // outside a transition. + // + // This path should only happen if the hydration lane already suspended. + // Currently, it also happens during sync updates because there is no + // hydration lane for sync updates. + // TODO: We should ideally have a sync hydration lane that we can apply to do + // a pass where we hydrate this subtree in place using the previous Context and then + // reapply the update afterwards. + + if (isSuspenseInstancePending()); + else { + renderDidSuspendDelayIfPossible(); + } + + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + null + ); + } else if (isSuspenseInstancePending()) { + // This component is still pending more data from the server, so we can't hydrate its + // content. We treat it as if this component suspended itself. It might seem as if + // we could just try to render it client-side instead. However, this will perform a + // lot of unnecessary work and is unlikely to complete since it often will suspend + // on missing data anyway. Additionally, the server might be able to render more + // than we can on the client yet. In that case we'd end up with more fallback states + // on the client than if we just leave it alone. If the server times out or errors + // these should update this boundary to the permanent Fallback state instead. + // Mark it as having captured (i.e. suspended). + workInProgress.flags |= DidCapture; // Leave the child in place. I.e. the dehydrated fragment. + + workInProgress.child = current.child; // Register a callback to retry this boundary once the server has sent the result. + + retryDehydratedSuspenseBoundary.bind(null, current); + registerSuspenseInstanceRetry(); + return null; + } else { + var primaryChildren = nextProps.children; + var primaryChildFragment = mountSuspensePrimaryChildren( + workInProgress, + primaryChildren + ); // Mark the children as hydrating. This is a fast path to know whether this + // tree is part of a hydrating tree. This is used to determine if a child + // node has fully mounted yet, and for scheduling event replaying. + // Conceptually this is similar to Placement in that a new subtree is + // inserted into the React tree here. It just happens to not need DOM + // mutations because it already exists. + + primaryChildFragment.flags |= Hydrating; + return primaryChildFragment; + } + } else { + // This is the second render pass. We already attempted to hydrated, but + // something either suspended or errored. + if (workInProgress.flags & ForceClientRender) { + // Something errored during hydration. Try again without hydrating. + pushPrimaryTreeSuspenseHandler(workInProgress); + workInProgress.flags &= ~ForceClientRender; + + var _capturedValue = createCapturedValue( + new Error( + "There was an error while hydrating this Suspense boundary. " + + "Switched to client rendering." + ) ); - didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true; + return retrySuspenseComponentWithoutHydrating( + current, + workInProgress, + renderLanes, + _capturedValue + ); + } else if (workInProgress.memoizedState !== null) { + // Something suspended and we should still be in dehydrated mode. + // Leave the existing child in place. + // Push to avoid a mismatch + pushFallbackTreeSuspenseHandler(workInProgress); + workInProgress.child = current.child; // The dehydrated completion pass expects this flag to be there + // but the normal suspense pass doesn't. + + workInProgress.flags |= DidCapture; + return null; + } else { + // Suspended but we should no longer be in dehydrated mode. + // Therefore we now have to render the fallback. + pushFallbackTreeSuspenseHandler(workInProgress); + var nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; + var fallbackChildFragment = + mountSuspenseFallbackAfterRetryWithoutHydrating( + current, + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); + var _primaryChildFragment4 = workInProgress.child; + _primaryChildFragment4.memoizedState = + mountSuspenseOffscreenState(renderLanes); + workInProgress.memoizedState = SUSPENDED_MARKER; + return fallbackChildFragment; } } } - var child = createFiberFromTypeAndProps( - Component.type, - null, - nextProps, - null, - workInProgress, - workInProgress.mode, - renderLanes - ); - child.ref = workInProgress.ref; - child.return = workInProgress; - workInProgress.child = child; - return child; - } - - { - var _type = Component.type; - var _innerPropTypes = _type.propTypes; - - if (_innerPropTypes) { - // Inner memo component props aren't currently validated in createElement. - // We could move it there, but we'd still need this for lazy code path. - checkPropTypes( - _innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(_type) + function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { + fiber.lanes = mergeLanes(fiber.lanes, renderLanes); + var alternate = fiber.alternate; + + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); + } + + scheduleContextWorkOnParentPath( + fiber.return, + renderLanes, + propagationRoot ); } - } - var currentChild = current.child; // This is always exactly one child + function propagateSuspenseContextChange( + workInProgress, + firstChild, + renderLanes + ) { + // Mark any Suspense boundaries with fallbacks as having work to do. + // If they were previously forced into fallbacks, they may now be able + // to unblock. + var node = firstChild; - var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( - current, - renderLanes - ); + while (node !== null) { + if (node.tag === SuspenseComponent) { + var state = node.memoizedState; - if (!hasScheduledUpdateOrContext) { - // This will be the props with resolved defaultProps, - // unlike current.memoizedProps which will be the unresolved ones. - var prevProps = currentChild.memoizedProps; // Default to shallow comparison + if (state !== null) { + scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); + } + } else if (node.tag === SuspenseListComponent) { + // If the tail is hidden there might not be an Suspense boundaries + // to schedule work on. In this case we have to schedule it on the + // list itself. + // We don't have to traverse to the children of the list since + // the list will propagate the change when it rerenders. + scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } - var compare = Component.compare; - compare = compare !== null ? compare : shallowEqual; + if (node === workInProgress) { + return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow - if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } - } // React DevTools reads this flag. + while (node.sibling === null) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + if (node.return === null || node.return === workInProgress) { + return; + } - workInProgress.flags |= PerformedWork; - var newChild = createWorkInProgress(currentChild, nextProps); - newChild.ref = workInProgress.ref; - newChild.return = workInProgress; - workInProgress.child = newChild; - return newChild; -} + node = node.return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow -function updateSimpleMemoComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - // TODO: current can be non-null here even if the component - // hasn't yet mounted. This happens when the inner render suspends. - // We'll need to figure out if this is fine or can cause issues. - { - if (workInProgress.type !== workInProgress.elementType) { - // Lazy component props can't be validated in createElement - // because they're only guaranteed to be resolved here. - var outerMemoType = workInProgress.elementType; - - if (outerMemoType.$$typeof === REACT_LAZY_TYPE) { - // We warn when you define propTypes on lazy() - // so let's just skip over it to find memo() outer wrapper. - // Inner props for memo are validated later. - var lazyComponent = outerMemoType; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + node.sibling.return = node.return; + node = node.sibling; + } + } - try { - outerMemoType = init(payload); - } catch (x) { - outerMemoType = null; - } // Inner propTypes will be validated in the function component path. + function findLastContentRow(firstChild) { + // This is going to find the last row among these children that is already + // showing content on the screen, as opposed to being in fallback state or + // new. If a row has multiple Suspense boundaries, any of them being in the + // fallback state, counts as the whole row being in a fallback state. + // Note that the "rows" will be workInProgress, but any nested children + // will still be current since we haven't rendered them yet. The mounted + // order may not be the same as the new order. We use the new order. + var row = firstChild; + var lastContentRow = null; - var outerPropTypes = outerMemoType && outerMemoType.propTypes; + while (row !== null) { + var currentRow = row.alternate; // New rows can't be content rows. - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - nextProps, // Resolved (SimpleMemoComponent has no defaultProps) - "prop", - getComponentNameFromType(outerMemoType) - ); + if (currentRow !== null && findFirstSuspended(currentRow) === null) { + lastContentRow = row; } + + row = row.sibling; } + + return lastContentRow; } - } - if (current !== null) { - var prevProps = current.memoizedProps; + function validateRevealOrder(revealOrder) { + { + if ( + revealOrder !== undefined && + revealOrder !== "forwards" && + revealOrder !== "backwards" && + revealOrder !== "together" && + !didWarnAboutRevealOrder[revealOrder] + ) { + didWarnAboutRevealOrder[revealOrder] = true; - if ( - shallowEqual(prevProps, nextProps) && - current.ref === workInProgress.ref && // Prevent bailout if the implementation changed due to hot reload. - workInProgress.type === current.type - ) { - didReceiveUpdate = false; // The props are shallowly equal. Reuse the previous props object, like we - // would during a normal fiber bailout. - // - // We don't have strong guarantees that the props object is referentially - // equal during updates where we can't bail out anyway — like if the props - // are shallowly equal, but there's a local state or context update in the - // same batch. - // - // However, as a principle, we should aim to make the behavior consistent - // across different ways of memoizing a component. For example, React.memo - // has a different internal Fiber layout if you pass a normal function - // component (SimpleMemoComponent) versus if you pass a different type - // like forwardRef (MemoComponent). But this is an implementation detail. - // Wrapping a component in forwardRef (or React.lazy, etc) shouldn't - // affect whether the props object is reused during a bailout. - - workInProgress.pendingProps = nextProps = prevProps; - - if (!checkScheduledUpdateOrContext(current, renderLanes)) { - // The pending lanes were cleared at the beginning of beginWork. We're - // about to bail out, but there might be other lanes that weren't - // included in the current render. Usually, the priority level of the - // remaining updates is accumulated during the evaluation of the - // component (i.e. when processing the update queue). But since since - // we're bailing out early *without* evaluating the component, we need - // to account for it here, too. Reset to the value of the current fiber. - // NOTE: This only applies to SimpleMemoComponent, not MemoComponent, - // because a MemoComponent fiber does not have hooks or an update queue; - // rather, it wraps around an inner component, which may or may not - // contains hooks. - // TODO: Move the reset at in beginWork out of the common path so that - // this is no longer necessary. - workInProgress.lanes = current.lanes; - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - ); - } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags$1) { - // This is a special case that only exists for legacy mode. - // See https://github.com/facebook/react/pull/19216. - didReceiveUpdate = true; - } - } - } + if (typeof revealOrder === "string") { + switch (revealOrder.toLowerCase()) { + case "together": + case "forwards": + case "backwards": { + error( + '"%s" is not a valid value for revealOrder on . ' + + 'Use lowercase "%s" instead.', + revealOrder, + revealOrder.toLowerCase() + ); - return updateFunctionComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes - ); -} + break; + } -function updateOffscreenComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; - var nextChildren = nextProps.children; - var nextIsDetached = - (workInProgress.stateNode._pendingVisibility & OffscreenDetached) !== 0; - var prevState = current !== null ? current.memoizedState : null; - markRef$1(current, workInProgress); - - if ( - nextProps.mode === "hidden" || - nextProps.mode === "unstable-defer-without-hiding" || - nextIsDetached - ) { - // Rendering a hidden tree. - var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags$1; - - if (didSuspend) { - // Something suspended inside a hidden tree - // Include the base lanes from the last render - var nextBaseLanes = - prevState !== null - ? mergeLanes(prevState.baseLanes, renderLanes) - : renderLanes; + case "forward": + case "backward": { + error( + '"%s" is not a valid value for revealOrder on . ' + + 'React uses the -s suffix in the spelling. Use "%ss" instead.', + revealOrder, + revealOrder.toLowerCase() + ); - if (current !== null) { - // Reset to the current children - var currentChild = (workInProgress.child = current.child); // The current render suspended, but there may be other lanes with - // pending work. We can't read `childLanes` from the current Offscreen - // fiber because we reset it when it was deferred; however, we can read - // the pending lanes from the child fibers. - - var currentChildLanes = NoLanes; - - while (currentChild !== null) { - currentChildLanes = mergeLanes( - mergeLanes(currentChildLanes, currentChild.lanes), - currentChild.childLanes - ); - currentChild = currentChild.sibling; - } + break; + } - var lanesWeJustAttempted = nextBaseLanes; - var remainingChildLanes = removeLanes( - currentChildLanes, - lanesWeJustAttempted - ); - workInProgress.childLanes = remainingChildLanes; - } else { - workInProgress.childLanes = NoLanes; - workInProgress.child = null; - } + default: + error( + '"%s" is not a supported revealOrder on . ' + + 'Did you mean "together", "forwards" or "backwards"?', + revealOrder + ); - return deferHiddenOffscreenComponent( - current, - workInProgress, - nextBaseLanes, - renderLanes - ); + break; + } + } else { + error( + "%s is not a supported value for revealOrder on . " + + 'Did you mean "together", "forwards" or "backwards"?', + revealOrder + ); + } + } + } } - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - // In legacy sync mode, don't defer the subtree. Render it now. - // TODO: Consider how Offscreen should work with transitions in the future - var nextState = { - baseLanes: NoLanes, - cachePool: null - }; - workInProgress.memoizedState = nextState; - + function validateTailOptions(tailMode, revealOrder) { { - // push the cache pool even though we're going to bail out - // because otherwise there'd be a context mismatch - if (current !== null) { - pushTransition(workInProgress, null, null); + if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) { + if (tailMode !== "collapsed" && tailMode !== "hidden") { + didWarnAboutTailOptions[tailMode] = true; + + error( + '"%s" is not a supported value for tail on . ' + + 'Did you mean "collapsed" or "hidden"?', + tailMode + ); + } else if ( + revealOrder !== "forwards" && + revealOrder !== "backwards" + ) { + didWarnAboutTailOptions[tailMode] = true; + + error( + ' is only valid if revealOrder is ' + + '"forwards" or "backwards". ' + + 'Did you mean to specify revealOrder="forwards"?', + tailMode + ); + } } } + } - reuseHiddenContextOnStack(workInProgress); - pushOffscreenSuspenseHandler(workInProgress); - } else if (!includesSomeLane(renderLanes, OffscreenLane)) { - // We're hidden, and we're not rendering at Offscreen. We will bail out - // and resume this tree later. - // Schedule this fiber to re-render at Offscreen priority - workInProgress.lanes = workInProgress.childLanes = - laneToLanes(OffscreenLane); // Include the base lanes from the last render - - var _nextBaseLanes = - prevState !== null - ? mergeLanes(prevState.baseLanes, renderLanes) - : renderLanes; - - return deferHiddenOffscreenComponent( - current, - workInProgress, - _nextBaseLanes, - renderLanes - ); - } else { - // This is the second render. The surrounding visible content has already - // committed. Now we resume rendering the hidden tree. - // Rendering at offscreen, so we can clear the base lanes. - var _nextState = { - baseLanes: NoLanes, - cachePool: null - }; - workInProgress.memoizedState = _nextState; + function validateSuspenseListNestedChild(childSlot, index) { + { + var isAnArray = isArray(childSlot); + var isIterable = + !isAnArray && typeof getIteratorFn(childSlot) === "function"; - if (current !== null) { - // If the render that spawned this one accessed the cache pool, resume - // using the same cache. Unless the parent changed, since that means - // there was a refresh. - var prevCachePool = prevState !== null ? prevState.cachePool : null; // TODO: Consider if and how Offscreen pre-rendering should - // be attributed to the transition that spawned it + if (isAnArray || isIterable) { + var type = isAnArray ? "array" : "iterable"; - pushTransition(workInProgress, prevCachePool, null); - } // Push the lanes that were skipped when we bailed out. + error( + "A nested %s was passed to row #%s in . Wrap it in " + + "an additional SuspenseList to configure its revealOrder: " + + " ... " + + "{%s} ... " + + "", + type, + index, + type + ); - if (prevState !== null) { - pushHiddenContext(workInProgress, prevState); - } else { - reuseHiddenContextOnStack(workInProgress); + return false; + } } - pushOffscreenSuspenseHandler(workInProgress); + return true; } - } else { - // Rendering a visible tree. - if (prevState !== null) { - // We're going from hidden -> visible. - var _prevCachePool = null; + function validateSuspenseListChildren(children, revealOrder) { { - // If the render that spawned this one accessed the cache pool, resume - // using the same cache. Unless the parent changed, since that means - // there was a refresh. - _prevCachePool = prevState.cachePool; - } + if ( + (revealOrder === "forwards" || revealOrder === "backwards") && + children !== undefined && + children !== null && + children !== false + ) { + if (isArray(children)) { + for (var i = 0; i < children.length; i++) { + if (!validateSuspenseListNestedChild(children[i], i)) { + return; + } + } + } else { + var iteratorFn = getIteratorFn(children); - var transitions = null; + if (typeof iteratorFn === "function") { + var childrenIterator = iteratorFn.call(children); - if (enableTransitionTracing) { - // We have now gone from hidden to visible, so any transitions should - // be added to the stack to get added to any Offscreen/suspense children - var instance = workInProgress.stateNode; + if (childrenIterator) { + var step = childrenIterator.next(); + var _i = 0; + + for (; !step.done; step = childrenIterator.next()) { + if (!validateSuspenseListNestedChild(step.value, _i)) { + return; + } - if (instance !== null && instance._transitions != null) { - transitions = Array.from(instance._transitions); + _i++; + } + } + } else { + error( + 'A single row was passed to a . ' + + "This is not useful since it needs multiple rows. " + + "Did you mean to pass multiple children or an array?", + revealOrder + ); + } + } } } + } - pushTransition(workInProgress, _prevCachePool, transitions); // Push the lanes that were skipped when we bailed out. - - pushHiddenContext(workInProgress, prevState); - reuseSuspenseHandlerOnStack(workInProgress); // Since we're not hidden anymore, reset the state + function initSuspenseListRenderState( + workInProgress, + isBackwards, + tail, + lastContentRow, + tailMode + ) { + var renderState = workInProgress.memoizedState; - workInProgress.memoizedState = null; - } else { - // We weren't previously hidden, and we still aren't, so there's nothing - // special to do. Need to push to the stack regardless, though, to avoid - // a push/pop misalignment. - { - // If the render that spawned this one accessed the cache pool, resume - // using the same cache. Unless the parent changed, since that means - // there was a refresh. - if (current !== null) { - pushTransition(workInProgress, null, null); - } - } // We're about to bail out, but we need to push this to the stack anyway - // to avoid a push/pop misalignment. + if (renderState === null) { + workInProgress.memoizedState = { + isBackwards: isBackwards, + rendering: null, + renderingStartTime: 0, + last: lastContentRow, + tail: tail, + tailMode: tailMode + }; + } else { + // We can reuse the existing object from previous renders. + renderState.isBackwards = isBackwards; + renderState.rendering = null; + renderState.renderingStartTime = 0; + renderState.last = lastContentRow; + renderState.tail = tail; + renderState.tailMode = tailMode; + } + } // This can end up rendering this component multiple passes. + // The first pass splits the children fibers into two sets. A head and tail. + // We first render the head. If anything is in fallback state, we do another + // pass through beginWork to rerender all children (including the tail) with + // the force suspend context. If the first render didn't have anything in + // in fallback state. Then we render each row in the tail one-by-one. + // That happens in the completeWork phase without going back to beginWork. + + function updateSuspenseListComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var revealOrder = nextProps.revealOrder; + var tailMode = nextProps.tail; + var newChildren = nextProps.children; + validateRevealOrder(revealOrder); + validateTailOptions(tailMode, revealOrder); + validateSuspenseListChildren(newChildren, revealOrder); + reconcileChildren(current, workInProgress, newChildren, renderLanes); + var suspenseContext = suspenseStackCursor.current; + var shouldForceFallback = hasSuspenseListContext( + suspenseContext, + ForceSuspenseFallback + ); - reuseHiddenContextOnStack(workInProgress); - reuseSuspenseHandlerOnStack(workInProgress); - } - } + if (shouldForceFallback) { + suspenseContext = setShallowSuspenseListContext( + suspenseContext, + ForceSuspenseFallback + ); + workInProgress.flags |= DidCapture; + } else { + var didSuspendBefore = + current !== null && (current.flags & DidCapture) !== NoFlags$1; + + if (didSuspendBefore) { + // If we previously forced a fallback, we need to schedule work + // on any nested boundaries to let them know to try to render + // again. This is the same as context updating. + propagateSuspenseContextChange( + workInProgress, + workInProgress.child, + renderLanes + ); + } - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + suspenseContext = setDefaultShallowSuspenseListContext(suspenseContext); + } -function deferHiddenOffscreenComponent( - current, - workInProgress, - nextBaseLanes, - renderLanes -) { - var nextState = { - baseLanes: nextBaseLanes, - // Save the cache pool so we can resume later. - cachePool: getOffscreenDeferredCache() - }; - workInProgress.memoizedState = nextState; - - { - // push the cache pool even though we're going to bail out - // because otherwise there'd be a context mismatch - if (current !== null) { - pushTransition(workInProgress, null, null); - } - } // We're about to bail out, but we need to push this to the stack anyway - // to avoid a push/pop misalignment. - - reuseHiddenContextOnStack(workInProgress); - pushOffscreenSuspenseHandler(workInProgress); - - if (enableLazyContextPropagation && current !== null) { - // Since this tree will resume rendering in a separate render, we need - // to propagate parent contexts now so we don't lose track of which - // ones changed. - propagateParentContextChangesToDeferredTree( - current, - workInProgress, - renderLanes - ); - } + pushSuspenseListContext(workInProgress, suspenseContext); - return null; -} // Note: These happen to have identical begin phases, for now. We shouldn't hold -// ourselves to this constraint, though. If the behavior diverges, we should -// fork the function. + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + // In legacy mode, SuspenseList doesn't work so we just + // use make it a noop by treating it as the default revealOrder. + workInProgress.memoizedState = null; + } else { + switch (revealOrder) { + case "forwards": { + var lastContentRow = findLastContentRow(workInProgress.child); + var tail; + + if (lastContentRow === null) { + // The whole list is part of the tail. + // TODO: We could fast path by just rendering the tail now. + tail = workInProgress.child; + workInProgress.child = null; + } else { + // Disconnect the tail rows after the content row. + // We're going to render them separately later. + tail = lastContentRow.sibling; + lastContentRow.sibling = null; + } -var updateLegacyHiddenComponent = updateOffscreenComponent; + initSuspenseListRenderState( + workInProgress, + false, // isBackwards + tail, + lastContentRow, + tailMode + ); + break; + } -function updateCacheComponent(current, workInProgress, renderLanes) { - prepareToReadContext(workInProgress, renderLanes); - var parentCache = readContext(CacheContext); + case "backwards": { + // We're going to find the first row that has existing content. + // At the same time we're going to reverse the list of everything + // we pass in the meantime. That's going to be our tail in reverse + // order. + var _tail = null; + var row = workInProgress.child; + workInProgress.child = null; - if (current === null) { - // Initial mount. Request a fresh cache from the pool. - var freshCache = requestCacheFromPool(renderLanes); - var initialState = { - parent: parentCache, - cache: freshCache - }; - workInProgress.memoizedState = initialState; - initializeUpdateQueue(workInProgress); - pushCacheProvider(workInProgress, freshCache); - } else { - // Check for updates - if (includesSomeLane(current.lanes, renderLanes)) { - cloneUpdateQueue(current, workInProgress); - processUpdateQueue(workInProgress, null, null, renderLanes); - } + while (row !== null) { + var currentRow = row.alternate; // New rows can't be content rows. - var prevState = current.memoizedState; - var nextState = workInProgress.memoizedState; // Compare the new parent cache to the previous to see detect there was - // a refresh. + if ( + currentRow !== null && + findFirstSuspended(currentRow) === null + ) { + // This is the beginning of the main content. + workInProgress.child = row; + break; + } - if (prevState.parent !== parentCache) { - // Refresh in parent. Update the parent. - var derivedState = { - parent: parentCache, - cache: parentCache - }; // Copied from getDerivedStateFromProps implementation. Once the update - // queue is empty, persist the derived state onto the base state. + var nextRow = row.sibling; + row.sibling = _tail; + _tail = row; + row = nextRow; + } // TODO: If workInProgress.child is null, we can continue on the tail immediately. + + initSuspenseListRenderState( + workInProgress, + true, // isBackwards + _tail, + null, // last + tailMode + ); + break; + } - workInProgress.memoizedState = derivedState; + case "together": { + initSuspenseListRenderState( + workInProgress, + false, // isBackwards + null, // tail + null, // last + undefined + ); + break; + } - if (workInProgress.lanes === NoLanes) { - var updateQueue = workInProgress.updateQueue; - workInProgress.memoizedState = updateQueue.baseState = derivedState; + default: { + // The default reveal order is the same as not having + // a boundary. + workInProgress.memoizedState = null; + } + } } - pushCacheProvider(workInProgress, parentCache); // No need to propagate a context change because the refreshed parent - // already did. - } else { - // The parent didn't refresh. Now check if this cache did. - var nextCache = nextState.cache; - pushCacheProvider(workInProgress, nextCache); - - if (nextCache !== prevState.cache) { - // This cache refreshed. Propagate a context change. - propagateContextChange(workInProgress, CacheContext, renderLanes); - } + return workInProgress.child; } - } - - var nextChildren = workInProgress.pendingProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} // This should only be called if the name changes - -function updateTracingMarkerComponent(current, workInProgress, renderLanes) { - if (!enableTransitionTracing) { - return null; - } // TODO: (luna) Only update the tracing marker if it's newly rendered or it's name changed. - // A tracing marker is only associated with the transitions that rendered - // or updated it, so we can create a new set of transitions each time - if (current === null) { - var currentTransitions = getPendingTransitions(); - - if (currentTransitions !== null) { - var markerInstance = { - tag: TransitionTracingMarker, - transitions: new Set(currentTransitions), - pendingBoundaries: null, - name: workInProgress.pendingProps.name, - aborts: null - }; - workInProgress.stateNode = markerInstance; // We call the marker complete callback when all child suspense boundaries resolve. - // We do this in the commit phase on Offscreen. If the marker has no child suspense - // boundaries, we need to schedule a passive effect to make sure we call the marker - // complete callback. - - workInProgress.flags |= Passive$1; - } - } else { - { - if (current.memoizedProps.name !== workInProgress.pendingProps.name) { - error( - "Changing the name of a tracing marker after mount is not supported. " + - "To remount the tracing marker, pass it a new key." + function updatePortalComponent(current, workInProgress, renderLanes) { + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + var nextChildren = workInProgress.pendingProps; + + if (current === null) { + // Portals are special because we don't append the children during mount + // but at commit. Therefore we need to track insertions which the normal + // flow doesn't do during mount. This doesn't happen at the root because + // the root always starts with a "current" with a null child. + // TODO: Consider unifying this with how the root works. + workInProgress.child = reconcileChildFibers( + workInProgress, + null, + nextChildren, + renderLanes ); + } else { + reconcileChildren(current, workInProgress, nextChildren, renderLanes); } + + return workInProgress.child; } - } - var instance = workInProgress.stateNode; + var hasWarnedAboutUsingNoValuePropOnContextProvider = false; - if (instance !== null) { - pushMarkerInstance(workInProgress, instance); - } + function updateContextProvider(current, workInProgress, renderLanes) { + var providerType = workInProgress.type; + var context = providerType._context; + var newProps = workInProgress.pendingProps; + var oldProps = workInProgress.memoizedProps; + var newValue = newProps.value; - var nextChildren = workInProgress.pendingProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + { + if (!("value" in newProps)) { + if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { + hasWarnedAboutUsingNoValuePropOnContextProvider = true; -function updateFragment(current, workInProgress, renderLanes) { - var nextChildren = workInProgress.pendingProps; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + error( + "The `value` prop is required for the ``. Did you misspell it or forget to pass it?" + ); + } + } -function updateMode(current, workInProgress, renderLanes) { - var nextChildren = workInProgress.pendingProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + var providerPropTypes = workInProgress.type.propTypes; -function updateProfiler(current, workInProgress, renderLanes) { - { - workInProgress.flags |= Update; + if (providerPropTypes) { + checkPropTypes( + providerPropTypes, + newProps, + "prop", + "Context.Provider" + ); + } + } - { - // Reset effect durations for the next eventual effect phase. - // These are reset during render to allow the DevTools commit hook a chance to read them, - var stateNode = workInProgress.stateNode; - stateNode.effectDuration = 0; - stateNode.passiveEffectDuration = 0; - } - } - - var nextProps = workInProgress.pendingProps; - var nextChildren = nextProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + pushProvider(workInProgress, context, newValue); -function markRef$1(current, workInProgress) { - var ref = workInProgress.ref; - - if ( - (current === null && ref !== null) || - (current !== null && current.ref !== ref) - ) { - // Schedule a Ref effect - workInProgress.flags |= Ref; - workInProgress.flags |= RefStatic; - } -} + if (enableLazyContextPropagation); + else { + if (oldProps !== null) { + var oldValue = oldProps.value; -function updateFunctionComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - { - if (workInProgress.type !== workInProgress.elementType) { - // Lazy component props can't be validated in createElement - // because they're only guaranteed to be resolved here. - var innerPropTypes = Component.propTypes; - - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(Component) - ); + if (objectIs(oldValue, newValue)) { + // No change. Bailout early if children are the same. + if ( + oldProps.children === newProps.children && + !hasContextChanged() + ) { + return bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); + } + } else { + // The context value changed. Search for matching consumers and schedule + // them to update. + propagateContextChange(workInProgress, context, renderLanes); + } + } } - } - } - - var context; - var nextChildren; - prepareToReadContext(workInProgress, renderLanes); - - if (enableSchedulingProfiler) { - markComponentRenderStarted(workInProgress); - } + var newChildren = newProps.children; + reconcileChildren(current, workInProgress, newChildren, renderLanes); + return workInProgress.child; + } - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - nextChildren = renderWithHooks( - current, - workInProgress, - Component, - nextProps, - context, - renderLanes - ); - setIsRendering(false); - } + var hasWarnedAboutUsingContextAsConsumer = false; - if (enableSchedulingProfiler) { - markComponentRenderStopped(); - } + function updateContextConsumer(current, workInProgress, renderLanes) { + var context = workInProgress.type; // The logic below for Context differs depending on PROD or DEV mode. In + // DEV mode, we create a separate object for Context.Consumer that acts + // like a proxy to Context. This proxy object adds unnecessary code in PROD + // so we use the old behaviour (Context.Consumer references Context) to + // reduce size and overhead. The separate object references context via + // a property called "_context", which also gives us the ability to check + // in DEV mode if this property exists or not and warn if it does not. - if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } + { + if (context._context === undefined) { + // This may be because it's a Context (rather than a Consumer). + // Or it may be because it's older React where they're the same thing. + // We only want to warn if we're sure it's a new React. + if (context !== context.Consumer) { + if (!hasWarnedAboutUsingContextAsConsumer) { + hasWarnedAboutUsingContextAsConsumer = true; - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + error( + "Rendering directly is not supported and will be removed in " + + "a future major release. Did you mean to render instead?" + ); + } + } + } else { + context = context._context; + } + } -function replayFunctionComponent( - current, - workInProgress, - nextProps, - Component, - secondArg, - renderLanes -) { - // This function is used to replay a component that previously suspended, - // after its data resolves. It's a simplified version of - // updateFunctionComponent that reuses the hooks from the previous attempt. - prepareToReadContext(workInProgress, renderLanes); - - if (enableSchedulingProfiler) { - markComponentRenderStarted(workInProgress); - } - - var nextChildren = replaySuspendedComponentWithHooks( - current, - workInProgress, - Component, - nextProps, - secondArg - ); - - if (enableSchedulingProfiler) { - markComponentRenderStopped(); - } - - if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderLanes); - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } - - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + var newProps = workInProgress.pendingProps; + var render = newProps.children; -function updateClassComponent( - current, - workInProgress, - Component, - nextProps, - renderLanes -) { - { - // This is used by DevTools to force a boundary to error. - switch (shouldError(workInProgress)) { - case false: { - var _instance = workInProgress.stateNode; - var ctor = workInProgress.type; // TODO This way of resetting the error boundary state is a hack. - // Is there a better way to do this? - - var tempInstance = new ctor( - workInProgress.memoizedProps, - _instance.context - ); - var state = tempInstance.state; + { + if (typeof render !== "function") { + 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." + ); + } + } - _instance.updater.enqueueSetState(_instance, state, null); + prepareToReadContext(workInProgress, renderLanes); + var newValue = readContext(context); - break; + if (enableSchedulingProfiler) { + markComponentRenderStarted(workInProgress); } - case true: { - workInProgress.flags |= DidCapture; - workInProgress.flags |= ShouldCapture; // eslint-disable-next-line react-internal/prod-error-codes - - var error$1 = new Error("Simulated error coming from DevTools"); - var lane = pickArbitraryLane(renderLanes); - workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); // Schedule the error boundary to re-render using updated state + var newChildren; - var update = createClassErrorUpdate( - workInProgress, - createCapturedValueAtFiber(error$1, workInProgress), - lane - ); - enqueueCapturedUpdate(workInProgress, update); - break; + { + ReactCurrentOwner$1.current = workInProgress; + setIsRendering(true); + newChildren = render(newValue); + setIsRendering(false); } - } - if (workInProgress.type !== workInProgress.elementType) { - // Lazy component props can't be validated in createElement - // because they're only guaranteed to be resolved here. - var innerPropTypes = Component.propTypes; + if (enableSchedulingProfiler) { + markComponentRenderStopped(); + } // React DevTools reads this flag. - if (innerPropTypes) { - checkPropTypes( - innerPropTypes, - nextProps, // Resolved props - "prop", - getComponentNameFromType(Component) - ); - } + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, newChildren, renderLanes); + return workInProgress.child; } - } // Push context providers early to prevent context stack mismatches. - // During mounting we don't know the child context yet as the instance doesn't exist. - // We will invalidate the child context in finishClassComponent() right after rendering. - var hasContext; + function updateScopeComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; + } - if (isContextProvider()) { - hasContext = true; - } else { - hasContext = false; - } + function markWorkInProgressReceivedUpdate() { + didReceiveUpdate = true; + } + function checkIfWorkInProgressReceivedUpdate() { + return didReceiveUpdate; + } - prepareToReadContext(workInProgress, renderLanes); - var instance = workInProgress.stateNode; - var shouldUpdate; + function resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + if (current !== null) { + // A lazy component only mounts if it suspended inside a non- + // concurrent tree, in an inconsistent state. We want to treat it like + // a new mount, even though an empty version of it already committed. + // Disconnect the alternate pointers. + current.alternate = null; + workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - if (instance === null) { - resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); // In the initial pass we might need to construct the instance. + workInProgress.flags |= Placement; + } + } + } - constructClassInstance(workInProgress, Component, nextProps); - mountClassInstance(workInProgress, Component, nextProps, renderLanes); - shouldUpdate = true; - } else if (current === null) { - // In a resume, we'll already have an instance we can reuse. - shouldUpdate = resumeMountClassInstance( - workInProgress, - Component, - nextProps, - renderLanes - ); - } else { - shouldUpdate = updateClassInstance( + function bailoutOnAlreadyFinishedWork( current, workInProgress, - Component, - nextProps, renderLanes - ); - } - - var nextUnitOfWork = finishClassComponent( - current, - workInProgress, - Component, - shouldUpdate, - hasContext, - renderLanes - ); - - { - var inst = workInProgress.stateNode; - - if (shouldUpdate && inst.props !== nextProps) { - if (!didWarnAboutReassigningProps) { - 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" - ); + ) { + if (current !== null) { + // Reuse previous dependencies + workInProgress.dependencies = current.dependencies; } - didWarnAboutReassigningProps = true; - } - } - - return nextUnitOfWork; -} - -function finishClassComponent( - current, - workInProgress, - Component, - shouldUpdate, - hasContext, - renderLanes -) { - // Refs should update even if shouldComponentUpdate returns false - markRef$1(current, workInProgress); - var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags$1; - - if (!shouldUpdate && !didCaptureError) { - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } - - var instance = workInProgress.stateNode; // Rerender - - ReactCurrentOwner$1.current = workInProgress; - var nextChildren; - - if ( - didCaptureError && - typeof Component.getDerivedStateFromError !== "function" - ) { - // If we captured an error, but getDerivedStateFromError is not defined, - // unmount all the children. componentDidCatch will schedule an update to - // re-render a fallback. This is temporary until we migrate everyone to - // the new API. - // TODO: Warn in a future release. - nextChildren = null; - - { - stopProfilerTimerIfRunning(); - } - } else { - if (enableSchedulingProfiler) { - markComponentRenderStarted(workInProgress); - } + { + // Don't update "base" render times for bailouts. + stopProfilerTimerIfRunning(); + } - { - setIsRendering(true); - nextChildren = instance.render(); + markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. - if (workInProgress.mode & StrictLegacyMode) { - setIsStrictModeForDevtools(true); + if (!includesSomeLane(renderLanes, workInProgress.childLanes)) { + // The children don't have any work either. We can skip them. + // TODO: Once we add back resuming, we should check if the children are + // a work-in-progress set. If so, we need to transfer their effects. + if (enableLazyContextPropagation && current !== null) { + // Before bailing out, check if there are any context changes in + // the children. + lazilyPropagateParentContextChanges( + current, + workInProgress, + renderLanes + ); - try { - instance.render(); - } finally { - setIsStrictModeForDevtools(false); + if (!includesSomeLane(renderLanes, workInProgress.childLanes)) { + return null; + } + } else { + return null; } - } + } // This fiber doesn't have work, but its subtree does. Clone the child + // fibers and continue. - setIsRendering(false); + cloneChildFibers(current, workInProgress); + return workInProgress.child; } - if (enableSchedulingProfiler) { - markComponentRenderStopped(); - } - } // React DevTools reads this flag. + function remountFiber(current, oldWorkInProgress, newWorkInProgress) { + { + var returnFiber = oldWorkInProgress.return; - workInProgress.flags |= PerformedWork; + if (returnFiber === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Cannot swap the root fiber."); + } // Disconnect from the old current. + // It will get deleted. - if (current !== null && didCaptureError) { - // If we're recovering from an error, reconcile without reusing any of - // the existing children. Conceptually, the normal children and the children - // that are shown on error are two different sets, so we shouldn't reuse - // normal children even if their identities match. - forceUnmountCurrentAndReconcile( - current, - workInProgress, - nextChildren, - renderLanes - ); - } else { - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - } // Memoize state using the values we just used to render. - // TODO: Restructure so we never read values from the instance. + current.alternate = null; + oldWorkInProgress.alternate = null; // Connect to the new tree. - workInProgress.memoizedState = instance.state; // The context might have changed so we need to recalculate it. + newWorkInProgress.index = oldWorkInProgress.index; + newWorkInProgress.sibling = oldWorkInProgress.sibling; + newWorkInProgress.return = oldWorkInProgress.return; + newWorkInProgress.ref = oldWorkInProgress.ref; // Replace the child/sibling pointers above it. - return workInProgress.child; -} + if (oldWorkInProgress === returnFiber.child) { + returnFiber.child = newWorkInProgress; + } else { + var prevSibling = returnFiber.child; -function pushHostRootContext(workInProgress) { - var root = workInProgress.stateNode; + if (prevSibling === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Expected parent to have a child."); + } // $FlowFixMe[incompatible-use] found when upgrading Flow - pushHostContainer(workInProgress, root.containerInfo); -} + while (prevSibling.sibling !== oldWorkInProgress) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + prevSibling = prevSibling.sibling; -function updateHostRoot(current, workInProgress, renderLanes) { - pushHostRootContext(workInProgress); + if (prevSibling === null) { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("Expected to find the previous sibling."); + } + } // $FlowFixMe[incompatible-use] found when upgrading Flow - if (current === null) { - throw new Error("Should have a current fiber. This is a bug in React."); - } + prevSibling.sibling = newWorkInProgress; + } // Delete the old fiber and place the new one. + // Since the old fiber is disconnected, we have to schedule it manually. - var nextProps = workInProgress.pendingProps; - var prevState = workInProgress.memoizedState; - var prevChildren = prevState.element; - cloneUpdateQueue(current, workInProgress); - processUpdateQueue(workInProgress, nextProps, null, renderLanes); - var nextState = workInProgress.memoizedState; - pushRootTransition(workInProgress); + var deletions = returnFiber.deletions; - if (enableTransitionTracing) { - pushRootMarkerInstance(workInProgress); - } + if (deletions === null) { + returnFiber.deletions = [current]; + returnFiber.flags |= ChildDeletion; + } else { + deletions.push(current); + } - { - var nextCache = nextState.cache; - pushCacheProvider(workInProgress, nextCache); + newWorkInProgress.flags |= Placement; // Restart work from the new fiber. - if (nextCache !== prevState.cache) { - // The root cache refreshed. - propagateContextChange(workInProgress, CacheContext, renderLanes); + return newWorkInProgress; + } } - } // Caution: React DevTools currently depends on this property - // being called "element". - var nextChildren = nextState.element; + function checkScheduledUpdateOrContext(current, renderLanes) { + // Before performing an early bailout, we must check if there are pending + // updates or context. + var updateLanes = current.lanes; - { - if (nextChildren === prevChildren) { - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - } + if (includesSomeLane(updateLanes, renderLanes)) { + return true; + } // No pending update, but because context is propagated lazily, we need + // to check for a context change before we bail out. - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - } + if (enableLazyContextPropagation) { + var dependencies = current.dependencies; - return workInProgress.child; -} + if (dependencies !== null && checkIfContextChanged(dependencies)) { + return true; + } + } -function updateHostComponent$1(current, workInProgress, renderLanes) { - pushHostContext(workInProgress); - - var type = workInProgress.type; - var nextProps = workInProgress.pendingProps; - var prevProps = current !== null ? current.memoizedProps : null; - var nextChildren = nextProps.children; - var isDirectTextChild = shouldSetTextContent(type, nextProps); - - if (isDirectTextChild) { - // We special case a direct text child of a host node. This is a common - // case. We won't handle it as a reified child. We will instead handle - // this in the host environment that also has access to this prop. That - // avoids allocating another HostText fiber and traversing it. - nextChildren = null; - } else if (prevProps !== null && shouldSetTextContent(type, prevProps)) { - // If we're switching from a direct text child to a normal child, or to - // empty, we need to schedule the text content to be reset. - workInProgress.flags |= ContentReset; - } - - markRef$1(current, workInProgress); - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} + return false; + } -function updateHostText$1(current, workInProgress) { - // immediately after. + function attemptEarlyBailoutIfNoScheduledUpdate( + current, + workInProgress, + renderLanes + ) { + // This fiber does not have any pending work. Bailout without entering + // the begin phase. There's still some bookkeeping we that needs to be done + // in this optimized path, mostly pushing stuff onto the stack. + switch (workInProgress.tag) { + case HostRoot: + pushHostRootContext(workInProgress); + pushRootTransition(workInProgress); - return null; -} + if (enableTransitionTracing) { + pushRootMarkerInstance(workInProgress); + } -function mountLazyComponent( - _current, - workInProgress, - elementType, - renderLanes -) { - resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); - var props = workInProgress.pendingProps; - var lazyComponent = elementType; - var payload = lazyComponent._payload; - var init = lazyComponent._init; - var Component = init(payload); // Store the unwrapped component in the type. - - workInProgress.type = Component; - var resolvedTag = (workInProgress.tag = resolveLazyComponentTag(Component)); - var resolvedProps = resolveDefaultProps(Component, props); - var child; - - switch (resolvedTag) { - case FunctionComponent: { - { - validateFunctionComponentInDev(workInProgress, Component); - workInProgress.type = Component = - resolveFunctionForHotReloading(Component); - } + { + var cache = current.memoizedState.cache; + pushCacheProvider(workInProgress, cache); + } + break; - child = updateFunctionComponent( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; - } + case HostSingleton: + case HostComponent: + pushHostContext(workInProgress); + break; - case ClassComponent: { - { - workInProgress.type = Component = - resolveClassForHotReloading(Component); - } + case ClassComponent: { + break; + } - child = updateClassComponent( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; - } + case HostPortal: + pushHostContainer( + workInProgress, + workInProgress.stateNode.containerInfo + ); + break; - case ForwardRef: { - { - workInProgress.type = Component = - resolveForwardRefForHotReloading(Component); - } + case ContextProvider: { + var newValue = workInProgress.memoizedProps.value; + var context = workInProgress.type._context; + pushProvider(workInProgress, context, newValue); + break; + } - child = updateForwardRef( - null, - workInProgress, - Component, - resolvedProps, - renderLanes - ); - return child; - } + case Profiler: + { + // Profiler should only call onRender when one of its descendants actually rendered. + var hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); - case MemoComponent: { - { - if (workInProgress.type !== workInProgress.elementType) { - var outerPropTypes = Component.propTypes; + if (hasChildWork) { + workInProgress.flags |= Update; + } - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - resolvedProps, // Resolved for outer only - "prop", - getComponentNameFromType(Component) - ); + { + // Reset effect durations for the next eventual effect phase. + // These are reset during render to allow the DevTools commit hook a chance to read them, + var stateNode = workInProgress.stateNode; + stateNode.effectDuration = 0; + stateNode.passiveEffectDuration = 0; + } } - } - } - child = updateMemoComponent( - null, - workInProgress, - Component, - resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too - renderLanes - ); - return child; - } - } + break; + + case SuspenseComponent: { + var state = workInProgress.memoizedState; - var hint = ""; + if (state !== null) { + if (state.dehydrated !== null) { + // We're not going to render the children, so this is just to maintain + // push/pop symmetry + pushPrimaryTreeSuspenseHandler(workInProgress); // We know that this component will suspend again because if it has + // been unsuspended it has committed as a resolved Suspense component. + // If it needs to be retried, it should have work scheduled on it. - { - if ( - Component !== null && - typeof Component === "object" && - Component.$$typeof === REACT_LAZY_TYPE - ) { - hint = " Did you wrap a component in React.lazy() more than once?"; - } - } // This message intentionally doesn't mention ForwardRef or MemoComponent - // because the fact that it's a separate type of work is an - // implementation detail. - - 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) - ); -} + workInProgress.flags |= DidCapture; // We should never render the children of a dehydrated boundary until we + // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork. -function mountIncompleteClassComponent( - _current, - workInProgress, - Component, - nextProps, - renderLanes -) { - resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); // Promote the fiber to a class and try rendering again. - - workInProgress.tag = ClassComponent; // The rest of this function is a fork of `updateClassComponent` - // Push context providers early to prevent context stack mismatches. - // During mounting we don't know the child context yet as the instance doesn't exist. - // We will invalidate the child context in finishClassComponent() right after rendering. - - var hasContext; - - if (isContextProvider()) { - hasContext = true; - } else { - hasContext = false; - } - - prepareToReadContext(workInProgress, renderLanes); - constructClassInstance(workInProgress, Component, nextProps); - mountClassInstance(workInProgress, Component, nextProps, renderLanes); - return finishClassComponent( - null, - workInProgress, - Component, - true, - hasContext, - renderLanes - ); -} + return null; + } // If this boundary is currently timed out, we need to decide + // whether to retry the primary children, or to skip over it and + // go straight to the fallback. Check the priority of the primary + // child fragment. -function mountIndeterminateComponent( - _current, - workInProgress, - Component, - renderLanes -) { - resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); - var props = workInProgress.pendingProps; - var context; + var primaryChildFragment = workInProgress.child; + var primaryChildLanes = primaryChildFragment.childLanes; + + if (includesSomeLane(renderLanes, primaryChildLanes)) { + // The primary children have pending work. Use the normal path + // to attempt to render the primary children again. + return updateSuspenseComponent( + current, + workInProgress, + renderLanes + ); + } else { + // The primary child fragment does not have pending work marked + // on it + pushPrimaryTreeSuspenseHandler(workInProgress); // The primary children do not have pending work with sufficient + // priority. Bailout. + + var child = bailoutOnAlreadyFinishedWork( + current, + workInProgress, + renderLanes + ); - prepareToReadContext(workInProgress, renderLanes); - var value; + if (child !== null) { + // The fallback children have pending work. Skip over the + // primary children and work on the fallback. + return child.sibling; + } else { + // Note: We can return `null` here because we already checked + // whether there were nested context consumers, via the call to + // `bailoutOnAlreadyFinishedWork` above. + return null; + } + } + } else { + pushPrimaryTreeSuspenseHandler(workInProgress); + } - if (enableSchedulingProfiler) { - markComponentRenderStarted(workInProgress); - } + break; + } - { - if ( - Component.prototype && - typeof Component.prototype.render === "function" - ) { - var componentName = getComponentNameFromType(Component) || "Unknown"; + case SuspenseListComponent: { + var didSuspendBefore = (current.flags & DidCapture) !== NoFlags$1; - if (!didWarnAboutBadClass[componentName]) { - 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 - ); + var _hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); - didWarnAboutBadClass[componentName] = true; - } - } + if (enableLazyContextPropagation && !_hasChildWork) { + // Context changes may not have been propagated yet. We need to do + // that now, before we can decide whether to bail out. + // TODO: We use `childLanes` as a heuristic for whether there is + // remaining work in a few places, including + // `bailoutOnAlreadyFinishedWork` and + // `updateDehydratedSuspenseComponent`. We should maybe extract this + // into a dedicated function. + lazilyPropagateParentContextChanges( + current, + workInProgress, + renderLanes + ); + _hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); + } - if (workInProgress.mode & StrictLegacyMode) { - ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null); - } + if (didSuspendBefore) { + if (_hasChildWork) { + // If something was in fallback state last time, and we have all the + // same children then we're still in progressive loading state. + // Something might get unblocked by state updates or retries in the + // tree which will affect the tail. So we need to use the normal + // path to compute the correct tail. + return updateSuspenseListComponent( + current, + workInProgress, + renderLanes + ); + } // If none of the children had any work, that means that none of + // them got retried so they'll still be blocked in the same way + // as before. We can fast bail out. - setIsRendering(true); - ReactCurrentOwner$1.current = workInProgress; - value = renderWithHooks( - null, - workInProgress, - Component, - props, - context, - renderLanes - ); - setIsRendering(false); - } + workInProgress.flags |= DidCapture; + } // If nothing suspended before and we're rendering the same children, + // then the tail doesn't matter. Anything new that suspends will work + // in the "together" mode, so we can continue from the state we had. + + var renderState = workInProgress.memoizedState; + + if (renderState !== null) { + // Reset to the "together" mode in case we've started a different + // update in the past but didn't complete it. + renderState.rendering = null; + renderState.tail = null; + renderState.lastEffect = null; + } - if (enableSchedulingProfiler) { - markComponentRenderStopped(); - } // React DevTools reads this flag. + pushSuspenseListContext(workInProgress, suspenseStackCursor.current); - workInProgress.flags |= PerformedWork; + if (_hasChildWork) { + break; + } else { + // If none of the children had any work, that means that none of + // them got retried so they'll still be blocked in the same way + // as before. We can fast bail out. + return null; + } + } - { - // Support for module components is deprecated and is removed behind a flag. - // Whether or not it would crash later, we want to show a good message in DEV first. - if ( - typeof value === "object" && - value !== null && - typeof value.render === "function" && - value.$$typeof === undefined - ) { - var _componentName = getComponentNameFromType(Component) || "Unknown"; + case OffscreenComponent: + case LegacyHiddenComponent: { + // Need to check if the tree still needs to be deferred. This is + // almost identical to the logic used in the normal update path, + // so we'll just enter that. The only difference is we'll bail out + // at the next level instead of this one, because the child props + // have not changed. Which is fine. + // TODO: Probably should refactor `beginWork` to split the bailout + // path from the normal path. I'm tempted to do a labeled break here + // but I won't :) + workInProgress.lanes = NoLanes; + return updateOffscreenComponent(current, workInProgress, renderLanes); + } - if (!didWarnAboutModulePatternComponent[_componentName]) { - 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 - ); + case CacheComponent: { + { + var _cache = current.memoizedState.cache; + pushCacheProvider(workInProgress, _cache); + } - didWarnAboutModulePatternComponent[_componentName] = true; - } - } - } + break; + } - { - // Proceed under the assumption that this is a function component - workInProgress.tag = FunctionComponent; + case TracingMarkerComponent: { + if (enableTransitionTracing) { + var instance = workInProgress.stateNode; - { - if (Component.contextTypes) { - error( - "%s uses the legacy contextTypes API which is no longer supported. " + - "Use React.createContext() with React.useContext() instead.", - getComponentNameFromType(Component) || "Unknown" - ); + if (instance !== null) { + pushMarkerInstance(workInProgress, instance); + } + } + } } + + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } - reconcileChildren(null, workInProgress, value, renderLanes); + function beginWork$1(current, workInProgress, renderLanes) { + { + if (workInProgress._debugNeedsRemount && current !== null) { + // This will restart the begin phase with a new fiber. + return remountFiber( + current, + workInProgress, + createFiberFromTypeAndProps( + workInProgress.type, + workInProgress.key, + workInProgress.pendingProps, + workInProgress._debugSource || null, + workInProgress._debugOwner || null, + workInProgress.mode, + workInProgress.lanes + ) + ); + } + } - { - validateFunctionComponentInDev(workInProgress, Component); - } + if (current !== null) { + var oldProps = current.memoizedProps; + var newProps = workInProgress.pendingProps; - return workInProgress.child; - } -} + if ( + oldProps !== newProps || + hasContextChanged() || // Force a re-render if the implementation changed due to hot reload: + workInProgress.type !== current.type + ) { + // If props or context changed, mark the fiber as having performed work. + // This may be unset if the props are determined to be equal later (memo). + didReceiveUpdate = true; + } else { + // Neither props nor legacy context changes. Check if there's a pending + // update or context change. + var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( + current, + renderLanes + ); -function validateFunctionComponentInDev(workInProgress, Component) { - { - if (Component) { - if (Component.childContextTypes) { - error( - "%s(...): childContextTypes cannot be defined on a function component.", - Component.displayName || Component.name || "Component" - ); - } - } + if ( + !hasScheduledUpdateOrContext && // If this is the second pass of an error or suspense boundary, there + // may not be work scheduled on `current`, so we check for this flag. + (workInProgress.flags & DidCapture) === NoFlags$1 + ) { + // No pending updates or context. Bail out now. + didReceiveUpdate = false; + return attemptEarlyBailoutIfNoScheduledUpdate( + current, + workInProgress, + renderLanes + ); + } - if (workInProgress.ref !== null) { - var info = ""; - var ownerName = getCurrentFiberOwnerNameInDevOrNull(); + if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags$1) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; + } else { + // An update was scheduled on this fiber, but there are no new props + // nor legacy context. Set this to false. If an update queue or context + // consumer produces a changed value, it will set this to true. Otherwise, + // the component will assume the children have not changed and bail out. + didReceiveUpdate = false; + } + } + } else { + didReceiveUpdate = false; + } // Before entering the begin phase, clear pending update priority. + // TODO: This assumes that we're about to evaluate the component and process + // the update queue. However, there's an exception: SimpleMemoComponent + // sometimes bails out later in the begin phase. This indicates that we should + // move this assignment out of the common path and into each branch. - if (ownerName) { - info += "\n\nCheck the render method of `" + ownerName + "`."; - } + workInProgress.lanes = NoLanes; - var warningKey = ownerName || ""; - var debugSource = workInProgress._debugSource; + switch (workInProgress.tag) { + case IndeterminateComponent: { + return mountIndeterminateComponent( + current, + workInProgress, + workInProgress.type, + renderLanes + ); + } - if (debugSource) { - warningKey = debugSource.fileName + ":" + debugSource.lineNumber; - } + case LazyComponent: { + var elementType = workInProgress.elementType; + return mountLazyComponent( + current, + workInProgress, + elementType, + renderLanes + ); + } - if (!didWarnAboutFunctionRefs[warningKey]) { - didWarnAboutFunctionRefs[warningKey] = true; + case FunctionComponent: { + var Component = workInProgress.type; + var unresolvedProps = workInProgress.pendingProps; + var resolvedProps = + workInProgress.elementType === Component + ? unresolvedProps + : resolveDefaultProps(Component, unresolvedProps); + return updateFunctionComponent( + current, + workInProgress, + Component, + resolvedProps, + renderLanes + ); + } - error( - "Function components cannot be given refs. " + - "Attempts to access this ref will fail. " + - "Did you mean to use React.forwardRef()?%s", - info - ); - } - } + case ClassComponent: { + var _Component = workInProgress.type; + var _unresolvedProps = workInProgress.pendingProps; - if (Component.defaultProps !== undefined) { - var componentName = getComponentNameFromType(Component) || "Unknown"; + var _resolvedProps = + workInProgress.elementType === _Component + ? _unresolvedProps + : resolveDefaultProps(_Component, _unresolvedProps); - if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) { - error( - "%s: Support for defaultProps will be removed from function components " + - "in a future major release. Use JavaScript default parameters instead.", - componentName - ); + return updateClassComponent( + current, + workInProgress, + _Component, + _resolvedProps, + renderLanes + ); + } - didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true; - } - } + case HostRoot: + return updateHostRoot(current, workInProgress, renderLanes); - if (typeof Component.getDerivedStateFromProps === "function") { - var _componentName3 = getComponentNameFromType(Component) || "Unknown"; + case HostHoistable: - if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { - error( - "%s: Function components do not support getDerivedStateFromProps.", - _componentName3 - ); + // Fall through - didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true; - } - } + case HostSingleton: - if ( - typeof Component.contextType === "object" && - Component.contextType !== null - ) { - var _componentName4 = getComponentNameFromType(Component) || "Unknown"; + // Fall through - if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { - error( - "%s: Function components do not support contextType.", - _componentName4 - ); + case HostComponent: + return updateHostComponent$1(current, workInProgress, renderLanes); - didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; - } - } - } -} + case HostText: + return updateHostText$1(); -var SUSPENDED_MARKER = { - dehydrated: null, - treeContext: null, - retryLane: NoLane -}; - -function mountSuspenseOffscreenState(renderLanes) { - return { - baseLanes: renderLanes, - cachePool: getSuspendedCache() - }; -} + case SuspenseComponent: + return updateSuspenseComponent(current, workInProgress, renderLanes); -function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { - var cachePool = null; + case HostPortal: + return updatePortalComponent(current, workInProgress, renderLanes); - { - var prevCachePool = prevOffscreenState.cachePool; + case ForwardRef: { + var type = workInProgress.type; + var _unresolvedProps2 = workInProgress.pendingProps; - if (prevCachePool !== null) { - var parentCache = CacheContext._currentValue2; + var _resolvedProps2 = + workInProgress.elementType === type + ? _unresolvedProps2 + : resolveDefaultProps(type, _unresolvedProps2); - if (prevCachePool.parent !== parentCache) { - // Detected a refresh in the parent. This overrides any previously - // suspended cache. - cachePool = { - parent: parentCache, - pool: parentCache - }; - } else { - // We can reuse the cache from last time. The only thing that would have - // overridden it is a parent refresh, which we checked for above. - cachePool = prevCachePool; - } - } else { - // If there's no previous cache pool, grab the current one. - cachePool = getSuspendedCache(); - } - } - - return { - baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), - cachePool: cachePool - }; -} // TODO: Probably should inline this back - -function shouldRemainOnFallback(current, workInProgress, renderLanes) { - // If we're already showing a fallback, there are cases where we need to - // remain on that fallback regardless of whether the content has resolved. - // For example, SuspenseList coordinates when nested content appears. - // TODO: For compatibility with offscreen prerendering, this should also check - // whether the current fiber (if it exists) was visible in the previous tree. - if (current !== null) { - var suspenseState = current.memoizedState; - - if (suspenseState === null) { - // Currently showing content. Don't hide it, even if ForceSuspenseFallback - // is true. More precise name might be "ForceRemainSuspenseFallback". - // Note: This is a factoring smell. Can't remain on a fallback if there's - // no fallback to remain on. - return false; - } - } // Not currently showing content. Consult the Suspense context. + return updateForwardRef( + current, + workInProgress, + type, + _resolvedProps2, + renderLanes + ); + } - var suspenseContext = suspenseStackCursor.current; - return hasSuspenseListContext(suspenseContext, ForceSuspenseFallback); -} + case Fragment: + return updateFragment(current, workInProgress, renderLanes); -function getRemainingWorkInPrimaryTree(current, renderLanes) { - // TODO: Should not remove render lanes that were pinged during this render - return removeLanes(current.childLanes, renderLanes); -} + case Mode: + return updateMode(current, workInProgress, renderLanes); -function updateSuspenseComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend. - - { - if (shouldSuspend(workInProgress)) { - workInProgress.flags |= DidCapture; - } - } - - var showFallback = false; - var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags$1; - - if (didSuspend || shouldRemainOnFallback(current)) { - // Something in this boundary's subtree already suspended. Switch to - // rendering the fallback children. - showFallback = true; - workInProgress.flags &= ~DidCapture; - } // OK, the next part is confusing. We're about to reconcile the Suspense - // boundary's children. This involves some custom reconciliation logic. Two - // main reasons this is so complicated. - // - // First, Legacy Mode has different semantics for backwards compatibility. The - // primary tree will commit in an inconsistent state, so when we do the - // second pass to render the fallback, we do some exceedingly, uh, clever - // hacks to make that not totally break. Like transferring effects and - // deletions from hidden tree. In Concurrent Mode, it's much simpler, - // because we bailout on the primary tree completely and leave it in its old - // state, no effects. Same as what we do for Offscreen (except that - // Offscreen doesn't have the first render pass). - // - // Second is hydration. During hydration, the Suspense fiber has a slightly - // different layout, where the child points to a dehydrated fragment, which - // contains the DOM rendered by the server. - // - // Third, even if you set all that aside, Suspense is like error boundaries in - // that we first we try to render one tree, and if that fails, we render again - // and switch to a different tree. Like a try/catch block. So we have to track - // which branch we're currently rendering. Ideally we would model this using - // a stack. - - if (current === null) { - var nextPrimaryChildren = nextProps.children; - var nextFallbackChildren = nextProps.fallback; - - if (showFallback) { - pushFallbackTreeSuspenseHandler(workInProgress); - var fallbackFragment = mountSuspenseFallbackChildren( - workInProgress, - nextPrimaryChildren, - nextFallbackChildren, - renderLanes - ); - var primaryChildFragment = workInProgress.child; - primaryChildFragment.memoizedState = - mountSuspenseOffscreenState(renderLanes); - workInProgress.memoizedState = SUSPENDED_MARKER; + case Profiler: + return updateProfiler(current, workInProgress, renderLanes); - if (enableTransitionTracing) { - var currentTransitions = getPendingTransitions(); + case ContextProvider: + return updateContextProvider(current, workInProgress, renderLanes); - if (currentTransitions !== null) { - var parentMarkerInstances = getMarkerInstances(); - var offscreenQueue = primaryChildFragment.updateQueue; - - if (offscreenQueue === null) { - var newOffscreenQueue = { - transitions: currentTransitions, - markerInstances: parentMarkerInstances, - retryQueue: null - }; - primaryChildFragment.updateQueue = newOffscreenQueue; - } else { - offscreenQueue.transitions = currentTransitions; - offscreenQueue.markerInstances = parentMarkerInstances; - } - } - } + case ContextConsumer: + return updateContextConsumer(current, workInProgress, renderLanes); - return fallbackFragment; - } else if (typeof nextProps.unstable_expectedLoadTime === "number") { - // This is a CPU-bound tree. Skip this tree and show a placeholder to - // unblock the surrounding content. Then immediately retry after the - // initial commit. - pushFallbackTreeSuspenseHandler(workInProgress); + case MemoComponent: { + var _type2 = workInProgress.type; + var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. - var _fallbackFragment = mountSuspenseFallbackChildren( - workInProgress, - nextPrimaryChildren, - nextFallbackChildren, - renderLanes - ); + var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); - var _primaryChildFragment = workInProgress.child; - _primaryChildFragment.memoizedState = - mountSuspenseOffscreenState(renderLanes); - workInProgress.memoizedState = SUSPENDED_MARKER; // TODO: Transition Tracing is not yet implemented for CPU Suspense. - // Since nothing actually suspended, there will nothing to ping this to - // get it started back up to attempt the next item. While in terms of - // priority this work has the same priority as this current render, it's - // not part of the same transition once the transition has committed. If - // it's sync, we still want to yield so that it can be painted. - // Conceptually, this is really the same as pinging. We can use any - // RetryLane even if it's the one currently rendering since we're leaving - // it behind on this node. - - workInProgress.lanes = SomeRetryLane; - return _fallbackFragment; - } else { - pushPrimaryTreeSuspenseHandler(workInProgress); - return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren); - } - } else { - // This is an update. - // Special path for hydration - var prevState = current.memoizedState; + { + if (workInProgress.type !== workInProgress.elementType) { + var outerPropTypes = _type2.propTypes; + + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + _resolvedProps3, // Resolved for outer only + "prop", + getComponentNameFromType(_type2) + ); + } + } + } - if (prevState !== null) { - var _dehydrated = prevState.dehydrated; + _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); + return updateMemoComponent( + current, + workInProgress, + _type2, + _resolvedProps3, + renderLanes + ); + } - if (_dehydrated !== null) { - return updateDehydratedSuspenseComponent( - current, - workInProgress, - didSuspend, - nextProps, - _dehydrated, - prevState, - renderLanes - ); - } - } + case SimpleMemoComponent: { + return updateSimpleMemoComponent( + current, + workInProgress, + workInProgress.type, + workInProgress.pendingProps, + renderLanes + ); + } - if (showFallback) { - pushFallbackTreeSuspenseHandler(workInProgress); - var _nextFallbackChildren = nextProps.fallback; - var _nextPrimaryChildren = nextProps.children; - var fallbackChildFragment = updateSuspenseFallbackChildren( - current, - workInProgress, - _nextPrimaryChildren, - _nextFallbackChildren, - renderLanes - ); - var _primaryChildFragment2 = workInProgress.child; - var prevOffscreenState = current.child.memoizedState; - _primaryChildFragment2.memoizedState = - prevOffscreenState === null - ? mountSuspenseOffscreenState(renderLanes) - : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); + case IncompleteClassComponent: { + var _Component2 = workInProgress.type; + var _unresolvedProps4 = workInProgress.pendingProps; - if (enableTransitionTracing) { - var _currentTransitions = getPendingTransitions(); + var _resolvedProps4 = + workInProgress.elementType === _Component2 + ? _unresolvedProps4 + : resolveDefaultProps(_Component2, _unresolvedProps4); - if (_currentTransitions !== null) { - var _parentMarkerInstances = getMarkerInstances(); + return mountIncompleteClassComponent( + current, + workInProgress, + _Component2, + _resolvedProps4, + renderLanes + ); + } - var _offscreenQueue = _primaryChildFragment2.updateQueue; - var currentOffscreenQueue = current.updateQueue; + case SuspenseListComponent: { + return updateSuspenseListComponent( + current, + workInProgress, + renderLanes + ); + } - if (_offscreenQueue === null) { - var _newOffscreenQueue = { - transitions: _currentTransitions, - markerInstances: _parentMarkerInstances, - retryQueue: null - }; - _primaryChildFragment2.updateQueue = _newOffscreenQueue; - } else if (_offscreenQueue === currentOffscreenQueue) { - // If the work-in-progress queue is the same object as current, we - // can't modify it without cloning it first. - var _newOffscreenQueue2 = { - transitions: _currentTransitions, - markerInstances: _parentMarkerInstances, - retryQueue: - currentOffscreenQueue !== null - ? currentOffscreenQueue.retryQueue - : null - }; - _primaryChildFragment2.updateQueue = _newOffscreenQueue2; - } else { - _offscreenQueue.transitions = _currentTransitions; - _offscreenQueue.markerInstances = _parentMarkerInstances; + case ScopeComponent: { + { + return updateScopeComponent(current, workInProgress, renderLanes); } } - } - _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree( - current, - renderLanes - ); - workInProgress.memoizedState = SUSPENDED_MARKER; - return fallbackChildFragment; - } else { - pushPrimaryTreeSuspenseHandler(workInProgress); - var _nextPrimaryChildren2 = nextProps.children; + case OffscreenComponent: { + return updateOffscreenComponent(current, workInProgress, renderLanes); + } - var _primaryChildFragment3 = updateSuspensePrimaryChildren( - current, - workInProgress, - _nextPrimaryChildren2, - renderLanes - ); + case LegacyHiddenComponent: { + { + return updateLegacyHiddenComponent( + current, + workInProgress, + renderLanes + ); + } + } - workInProgress.memoizedState = null; - return _primaryChildFragment3; - } - } -} + case CacheComponent: { + { + return updateCacheComponent(current, workInProgress, renderLanes); + } + } -function mountSuspensePrimaryChildren( - workInProgress, - primaryChildren, - renderLanes -) { - var mode = workInProgress.mode; - var primaryChildProps = { - mode: "visible", - children: primaryChildren - }; - var primaryChildFragment = mountWorkInProgressOffscreenFiber( - primaryChildProps, - mode - ); - primaryChildFragment.return = workInProgress; - workInProgress.child = primaryChildFragment; - return primaryChildFragment; -} + case TracingMarkerComponent: { + if (enableTransitionTracing) { + return updateTracingMarkerComponent( + current, + workInProgress, + renderLanes + ); + } -function mountSuspenseFallbackChildren( - workInProgress, - primaryChildren, - fallbackChildren, - renderLanes -) { - var mode = workInProgress.mode; - var progressedPrimaryFragment = workInProgress.child; - var primaryChildProps = { - mode: "hidden", - children: primaryChildren - }; - var primaryChildFragment; - var fallbackChildFragment; - - if ( - (mode & ConcurrentMode) === NoMode && - progressedPrimaryFragment !== null - ) { - // In legacy mode, we commit the primary tree as if it successfully - // completed, even though it's in an inconsistent state. - primaryChildFragment = progressedPrimaryFragment; - primaryChildFragment.childLanes = NoLanes; - primaryChildFragment.pendingProps = primaryChildProps; - - if (workInProgress.mode & ProfileMode) { - // Reset the durations from the first pass so they aren't included in the - // final amounts. This seems counterintuitive, since we're intentionally - // not measuring part of the render phase, but this makes it match what we - // do in Concurrent Mode. - primaryChildFragment.actualDuration = 0; - primaryChildFragment.actualStartTime = -1; - primaryChildFragment.selfBaseDuration = 0; - primaryChildFragment.treeBaseDuration = 0; - } - - fallbackChildFragment = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, - null - ); - } else { - primaryChildFragment = mountWorkInProgressOffscreenFiber( - primaryChildProps, - mode - ); - fallbackChildFragment = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, - null - ); - } + break; + } + } - primaryChildFragment.return = workInProgress; - fallbackChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; - workInProgress.child = primaryChildFragment; - return fallbackChildFragment; -} + throw new Error( + "Unknown unit of work tag (" + + workInProgress.tag + + "). This error is likely caused by a bug in " + + "React. Please file an issue." + ); + } -function mountWorkInProgressOffscreenFiber(offscreenProps, mode, renderLanes) { - // The props argument to `createFiberFromOffscreen` is `any` typed, so we use - // this wrapper function to constrain it. - return createFiberFromOffscreen(offscreenProps, mode, NoLanes, null); -} + var valueCursor = createCursor(null); -function updateWorkInProgressOffscreenFiber(current, offscreenProps) { - // The props argument to `createWorkInProgress` is `any` typed, so we use this - // wrapper function to constrain it. - return createWorkInProgress(current, offscreenProps); -} + var renderer2CursorDEV; -function updateSuspensePrimaryChildren( - current, - workInProgress, - primaryChildren, - renderLanes -) { - var currentPrimaryChildFragment = current.child; - var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; - var primaryChildFragment = updateWorkInProgressOffscreenFiber( - currentPrimaryChildFragment, { - mode: "visible", - children: primaryChildren + renderer2CursorDEV = createCursor(null); } - ); - - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - primaryChildFragment.lanes = renderLanes; - } - - primaryChildFragment.return = workInProgress; - primaryChildFragment.sibling = null; - if (currentFallbackChildFragment !== null) { - // Delete the fallback child fragment - var deletions = workInProgress.deletions; + var rendererSigil; - if (deletions === null) { - workInProgress.deletions = [currentFallbackChildFragment]; - workInProgress.flags |= ChildDeletion; - } else { - deletions.push(currentFallbackChildFragment); + { + // Use this to detect multiple renderers using the same context + rendererSigil = {}; } - } - - workInProgress.child = primaryChildFragment; - return primaryChildFragment; -} - -function updateSuspenseFallbackChildren( - current, - workInProgress, - primaryChildren, - fallbackChildren, - renderLanes -) { - var mode = workInProgress.mode; - var currentPrimaryChildFragment = current.child; - var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; - var primaryChildProps = { - mode: "hidden", - children: primaryChildren - }; - var primaryChildFragment; - - if ( - // In legacy mode, we commit the primary tree as if it successfully - // completed, even though it's in an inconsistent state. - (mode & ConcurrentMode) === NoMode && // Make sure we're on the second pass, i.e. the primary child fragment was - // already cloned. In legacy mode, the only case where this isn't true is - // when DevTools forces us to display a fallback; we skip the first render - // pass entirely and go straight to rendering the fallback. (In Concurrent - // Mode, SuspenseList can also trigger this scenario, but this is a legacy- - // only codepath.) - workInProgress.child !== currentPrimaryChildFragment - ) { - var progressedPrimaryFragment = workInProgress.child; - primaryChildFragment = progressedPrimaryFragment; - primaryChildFragment.childLanes = NoLanes; - primaryChildFragment.pendingProps = primaryChildProps; - - if (workInProgress.mode & ProfileMode) { - // Reset the durations from the first pass so they aren't included in the - // final amounts. This seems counterintuitive, since we're intentionally - // not measuring part of the render phase, but this makes it match what we - // do in Concurrent Mode. - primaryChildFragment.actualDuration = 0; - primaryChildFragment.actualStartTime = -1; - primaryChildFragment.selfBaseDuration = - currentPrimaryChildFragment.selfBaseDuration; - primaryChildFragment.treeBaseDuration = - currentPrimaryChildFragment.treeBaseDuration; - } // The fallback fiber was added as a deletion during the first pass. - // However, since we're going to remain on the fallback, we no longer want - // to delete it. - - workInProgress.deletions = null; - } else { - primaryChildFragment = updateWorkInProgressOffscreenFiber( - currentPrimaryChildFragment, - primaryChildProps - ); // Since we're reusing a current tree, we need to reuse the flags, too. - // (We don't do this in legacy mode, because in legacy mode we don't re-use - // the current tree; see previous branch.) - - primaryChildFragment.subtreeFlags = - currentPrimaryChildFragment.subtreeFlags & StaticMask; - } - - var fallbackChildFragment; - - if (currentFallbackChildFragment !== null) { - fallbackChildFragment = createWorkInProgress( - currentFallbackChildFragment, - fallbackChildren - ); - } else { - fallbackChildFragment = createFiberFromFragment( - fallbackChildren, - mode, - renderLanes, - null - ); // Needs a placement effect because the parent (the Suspense boundary) already - // mounted but this is a new fiber. - - fallbackChildFragment.flags |= Placement; - } - - fallbackChildFragment.return = workInProgress; - primaryChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; - workInProgress.child = primaryChildFragment; - return fallbackChildFragment; -} - -function retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - recoverableError -) { - // Falling back to client rendering. Because this has performance - // implications, it's considered a recoverable error, even though the user - // likely won't observe anything wrong with the UI. - // - // The error is passed in as an argument to enforce that every caller provide - // a custom message, or explicitly opt out (currently the only path that opts - // out is legacy mode; every concurrent path provides an error). - if (recoverableError !== null) { - queueHydrationError(recoverableError); - } // This will add the old fiber to the deletion list - - reconcileChildFibers(workInProgress, current.child, null, renderLanes); // We're now not suspended nor dehydrated. - - var nextProps = workInProgress.pendingProps; - var primaryChildren = nextProps.children; - var primaryChildFragment = mountSuspensePrimaryChildren( - workInProgress, - primaryChildren - ); // Needs a placement effect because the parent (the Suspense boundary) already - // mounted but this is a new fiber. - - primaryChildFragment.flags |= Placement; - workInProgress.memoizedState = null; - return primaryChildFragment; -} -function mountSuspenseFallbackAfterRetryWithoutHydrating( - current, - workInProgress, - primaryChildren, - fallbackChildren, - renderLanes -) { - var fiberMode = workInProgress.mode; - var primaryChildProps = { - mode: "visible", - children: primaryChildren - }; - var primaryChildFragment = mountWorkInProgressOffscreenFiber( - primaryChildProps, - fiberMode - ); - var fallbackChildFragment = createFiberFromFragment( - fallbackChildren, - fiberMode, - renderLanes, - null - ); // Needs a placement effect because the parent (the Suspense - // boundary) already mounted but this is a new fiber. - - fallbackChildFragment.flags |= Placement; - primaryChildFragment.return = workInProgress; - fallbackChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; - workInProgress.child = primaryChildFragment; - - if ((workInProgress.mode & ConcurrentMode) !== NoMode) { - // We will have dropped the effect list which contains the - // deletion. We need to reconcile to delete the current child. - reconcileChildFibers(workInProgress, current.child, null, renderLanes); - } - - return fallbackChildFragment; -} + var currentlyRenderingFiber = null; + var lastContextDependency = null; + var lastFullyObservedContext = null; + var isDisallowedContextReadInDEV = false; + function resetContextDependencies() { + // This is called right before React yields execution, to ensure `readContext` + // cannot be called outside the render phase. + currentlyRenderingFiber = null; + lastContextDependency = null; + lastFullyObservedContext = null; -function updateDehydratedSuspenseComponent( - current, - workInProgress, - didSuspend, - nextProps, - suspenseInstance, - suspenseState, - renderLanes -) { - if (!didSuspend) { - // This is the first render pass. Attempt to hydrate. - pushPrimaryTreeSuspenseHandler(workInProgress); // We should never be hydrating at this point because it is the first pass, - - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - null - ); + { + isDisallowedContextReadInDEV = false; + } } + function enterDisallowedContextReadInDEV() { + { + isDisallowedContextReadInDEV = true; + } + } + function exitDisallowedContextReadInDEV() { + { + isDisallowedContextReadInDEV = false; + } + } + function pushProvider(providerFiber, context, nextValue) { + { + push(valueCursor, context._currentValue2, providerFiber); + context._currentValue2 = nextValue; - if (isSuspenseInstanceFallback()) { - // This boundary is in a permanent fallback state. In this case, we'll never - // get an update and we'll never be able to hydrate the final content. Let's just try the - // client side render instead. - var digest; - var message, stack; + { + push(renderer2CursorDEV, context._currentRenderer2, providerFiber); - { - var _getSuspenseInstanceF = getSuspenseInstanceFallbackErrorDetails(); + if ( + context._currentRenderer2 !== undefined && + context._currentRenderer2 !== null && + context._currentRenderer2 !== rendererSigil + ) { + error( + "Detected multiple renderers concurrently rendering the " + + "same context provider. This is currently unsupported." + ); + } - digest = _getSuspenseInstanceF.digest; - message = _getSuspenseInstanceF.message; - stack = _getSuspenseInstanceF.stack; + context._currentRenderer2 = rendererSigil; + } } - - var capturedValue = null; // TODO: Figure out a better signal than encoding a magic digest value. + } + function popProvider(context, providerFiber) { + var currentValue = valueCursor.current; { - var error; - - if (message) { - // eslint-disable-next-line react-internal/prod-error-codes - error = new Error(message); - } else { - error = new Error( - "The server could not finish this Suspense boundary, likely " + - "due to an error during server rendering. Switched to " + - "client rendering." - ); + { + context._currentValue2 = currentValue; } - error.digest = digest; - capturedValue = createCapturedValue(error, digest, stack); + { + var currentRenderer2 = renderer2CursorDEV.current; + pop(renderer2CursorDEV, providerFiber); + context._currentRenderer2 = currentRenderer2; + } } - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - capturedValue - ); + pop(valueCursor, providerFiber); } - - if ( - enableLazyContextPropagation && // TODO: Factoring is a little weird, since we check this right below, too. - // But don't want to re-arrange the if-else chain until/unless this - // feature lands. - !didReceiveUpdate + function scheduleContextWorkOnParentPath( + parent, + renderLanes, + propagationRoot ) { - // We need to check if any children have context before we decide to bail - // out, so propagate the changes now. - lazilyPropagateParentContextChanges(current, workInProgress, renderLanes); - } // We use lanes to indicate that a child might depend on context, so if - // any context has changed, we need to treat is as if the input might have changed. - - var hasContextChanged = includesSomeLane(renderLanes, current.childLanes); + // Update the child lanes of all the ancestors, including the alternates. + var node = parent; - if (didReceiveUpdate || hasContextChanged) { - // This boundary has changed since the first render. This means that we are now unable to - // hydrate it. We might still be able to hydrate it using a higher priority lane. - var root = getWorkInProgressRoot(); + while (node !== null) { + var alternate = node.alternate; - if (root !== null) { - var attemptHydrationAtLane = getBumpedLaneForHydration( - root, - renderLanes - ); + if (!isSubsetOfLanes(node.childLanes, renderLanes)) { + node.childLanes = mergeLanes(node.childLanes, renderLanes); - if ( - attemptHydrationAtLane !== NoLane && - attemptHydrationAtLane !== suspenseState.retryLane + if (alternate !== null) { + alternate.childLanes = mergeLanes( + alternate.childLanes, + renderLanes + ); + } + } else if ( + alternate !== null && + !isSubsetOfLanes(alternate.childLanes, renderLanes) ) { - // Intentionally mutating since this render will get interrupted. This - // is one of the very rare times where we mutate the current tree - // during the render phase. - suspenseState.retryLane = attemptHydrationAtLane; - enqueueConcurrentRenderForLane(current, attemptHydrationAtLane); - scheduleUpdateOnFiber(root, current, attemptHydrationAtLane); // Throw a special object that signals to the work loop that it should - // interrupt the current render. - // - // Because we're inside a React-only execution stack, we don't - // strictly need to throw here — we could instead modify some internal - // work loop state. But using an exception means we don't need to - // check for this case on every iteration of the work loop. So doing - // it this way moves the check out of the fast path. + alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); + } else; - throw SelectiveHydrationException; + if (node === propagationRoot) { + break; } - } // If we did not selectively hydrate, we'll continue rendering without - // hydrating. Mark this tree as suspended to prevent it from committing - // outside a transition. - // - // This path should only happen if the hydration lane already suspended. - // Currently, it also happens during sync updates because there is no - // hydration lane for sync updates. - // TODO: We should ideally have a sync hydration lane that we can apply to do - // a pass where we hydrate this subtree in place using the previous Context and then - // reapply the update afterwards. - - if (isSuspenseInstancePending()); - else { - renderDidSuspendDelayIfPossible(); + + node = node.return; } - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - null - ); - } else if (isSuspenseInstancePending()) { - // This component is still pending more data from the server, so we can't hydrate its - // content. We treat it as if this component suspended itself. It might seem as if - // we could just try to render it client-side instead. However, this will perform a - // lot of unnecessary work and is unlikely to complete since it often will suspend - // on missing data anyway. Additionally, the server might be able to render more - // than we can on the client yet. In that case we'd end up with more fallback states - // on the client than if we just leave it alone. If the server times out or errors - // these should update this boundary to the permanent Fallback state instead. - // Mark it as having captured (i.e. suspended). - workInProgress.flags |= DidCapture; // Leave the child in place. I.e. the dehydrated fragment. - - workInProgress.child = current.child; // Register a callback to retry this boundary once the server has sent the result. - - retryDehydratedSuspenseBoundary.bind(null, current); - registerSuspenseInstanceRetry(); - return null; - } else { - var primaryChildren = nextProps.children; - var primaryChildFragment = mountSuspensePrimaryChildren( - workInProgress, - primaryChildren - ); // Mark the children as hydrating. This is a fast path to know whether this - // tree is part of a hydrating tree. This is used to determine if a child - // node has fully mounted yet, and for scheduling event replaying. - // Conceptually this is similar to Placement in that a new subtree is - // inserted into the React tree here. It just happens to not need DOM - // mutations because it already exists. - - primaryChildFragment.flags |= Hydrating; - return primaryChildFragment; + { + if (node !== propagationRoot) { + 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." + ); + } + } } - } else { - // This is the second render pass. We already attempted to hydrated, but - // something either suspended or errored. - if (workInProgress.flags & ForceClientRender) { - // Something errored during hydration. Try again without hydrating. - pushPrimaryTreeSuspenseHandler(workInProgress); - workInProgress.flags &= ~ForceClientRender; - - var _capturedValue = createCapturedValue( - new Error( - "There was an error while hydrating this Suspense boundary. " + - "Switched to client rendering." - ) - ); - - return retrySuspenseComponentWithoutHydrating( - current, - workInProgress, - renderLanes, - _capturedValue - ); - } else if (workInProgress.memoizedState !== null) { - // Something suspended and we should still be in dehydrated mode. - // Leave the existing child in place. - // Push to avoid a mismatch - pushFallbackTreeSuspenseHandler(workInProgress); - workInProgress.child = current.child; // The dehydrated completion pass expects this flag to be there - // but the normal suspense pass doesn't. - - workInProgress.flags |= DidCapture; - return null; - } else { - // Suspended but we should no longer be in dehydrated mode. - // Therefore we now have to render the fallback. - pushFallbackTreeSuspenseHandler(workInProgress); - var nextPrimaryChildren = nextProps.children; - var nextFallbackChildren = nextProps.fallback; - var fallbackChildFragment = - mountSuspenseFallbackAfterRetryWithoutHydrating( - current, + function propagateContextChange(workInProgress, context, renderLanes) { + if (enableLazyContextPropagation) { + // TODO: This path is only used by Cache components. Update + // lazilyPropagateParentContextChanges to look for Cache components so they + // can take advantage of lazy propagation. + var forcePropagateEntireTree = true; + propagateContextChanges( workInProgress, - nextPrimaryChildren, - nextFallbackChildren, - renderLanes + [context], + renderLanes, + forcePropagateEntireTree ); - var _primaryChildFragment4 = workInProgress.child; - _primaryChildFragment4.memoizedState = - mountSuspenseOffscreenState(renderLanes); - workInProgress.memoizedState = SUSPENDED_MARKER; - return fallbackChildFragment; + } else { + propagateContextChange_eager(workInProgress, context, renderLanes); + } } - } -} - -function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { - fiber.lanes = mergeLanes(fiber.lanes, renderLanes); - var alternate = fiber.alternate; - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, renderLanes); - } + function propagateContextChange_eager( + workInProgress, + context, + renderLanes + ) { + // Only used by eager implementation + if (enableLazyContextPropagation) { + return; + } - scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); -} + var fiber = workInProgress.child; -function propagateSuspenseContextChange( - workInProgress, - firstChild, - renderLanes -) { - // Mark any Suspense boundaries with fallbacks as having work to do. - // If they were previously forced into fallbacks, they may now be able - // to unblock. - var node = firstChild; - - while (node !== null) { - if (node.tag === SuspenseComponent) { - var state = node.memoizedState; - - if (state !== null) { - scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); - } - } else if (node.tag === SuspenseListComponent) { - // If the tail is hidden there might not be an Suspense boundaries - // to schedule work on. In this case we have to schedule it on the - // list itself. - // We don't have to traverse to the children of the list since - // the list will propagate the change when it rerenders. - scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } - - if (node === workInProgress) { - return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow - - while (node.sibling === null) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - if (node.return === null || node.return === workInProgress) { - return; + if (fiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + fiber.return = workInProgress; } - node = node.return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow + while (fiber !== null) { + var nextFiber = void 0; // Visit this fiber. - node.sibling.return = node.return; - node = node.sibling; - } -} + var list = fiber.dependencies; -function findLastContentRow(firstChild) { - // This is going to find the last row among these children that is already - // showing content on the screen, as opposed to being in fallback state or - // new. If a row has multiple Suspense boundaries, any of them being in the - // fallback state, counts as the whole row being in a fallback state. - // Note that the "rows" will be workInProgress, but any nested children - // will still be current since we haven't rendered them yet. The mounted - // order may not be the same as the new order. We use the new order. - var row = firstChild; - var lastContentRow = null; + if (list !== null) { + nextFiber = fiber.child; + var dependency = list.firstContext; - while (row !== null) { - var currentRow = row.alternate; // New rows can't be content rows. + while (dependency !== null) { + // Check if the context matches. + if (dependency.context === context) { + // Match! Schedule an update on this fiber. + if (fiber.tag === ClassComponent) { + // Schedule a force update on the work-in-progress. + var lane = pickArbitraryLane(renderLanes); + var update = createUpdate(lane); + update.tag = ForceUpdate; // TODO: Because we don't have a work-in-progress, this will add the + // update to the current fiber, too, which means it will persist even if + // this render is thrown away. Since it's a race condition, not sure it's + // worth fixing. + // Inlined `enqueueUpdate` to remove interleaved update check - if (currentRow !== null && findFirstSuspended(currentRow) === null) { - lastContentRow = row; - } + var updateQueue = fiber.updateQueue; - row = row.sibling; - } + if (updateQueue === null); + else { + var sharedQueue = updateQueue.shared; + var pending = sharedQueue.pending; - return lastContentRow; -} + if (pending === null) { + // This is the first update. Create a circular list. + update.next = update; + } else { + update.next = pending.next; + pending.next = update; + } -function validateRevealOrder(revealOrder) { - { - if ( - revealOrder !== undefined && - revealOrder !== "forwards" && - revealOrder !== "backwards" && - revealOrder !== "together" && - !didWarnAboutRevealOrder[revealOrder] - ) { - didWarnAboutRevealOrder[revealOrder] = true; + sharedQueue.pending = update; + } + } - if (typeof revealOrder === "string") { - switch (revealOrder.toLowerCase()) { - case "together": - case "forwards": - case "backwards": { - error( - '"%s" is not a valid value for revealOrder on . ' + - 'Use lowercase "%s" instead.', - revealOrder, - revealOrder.toLowerCase() - ); + fiber.lanes = mergeLanes(fiber.lanes, renderLanes); + var alternate = fiber.alternate; - break; - } + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); + } - case "forward": - case "backward": { - error( - '"%s" is not a valid value for revealOrder on . ' + - 'React uses the -s suffix in the spelling. Use "%ss" instead.', - revealOrder, - revealOrder.toLowerCase() - ); + scheduleContextWorkOnParentPath( + fiber.return, + renderLanes, + workInProgress + ); // Mark the updated lanes on the list, too. - break; - } + list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the + // dependency list. - default: - error( - '"%s" is not a supported revealOrder on . ' + - 'Did you mean "together", "forwards" or "backwards"?', - revealOrder + break; + } + + dependency = dependency.next; + } + } else if (fiber.tag === ContextProvider) { + // Don't scan deeper if this is a matching provider + nextFiber = fiber.type === workInProgress.type ? null : fiber.child; + } else if (fiber.tag === DehydratedFragment) { + // If a dehydrated suspense boundary is in this subtree, we don't know + // if it will have any context consumers in it. The best we can do is + // mark it as having updates. + var parentSuspense = fiber.return; + + if (parentSuspense === null) { + throw new Error( + "We just came from a parent so we must have had a parent. This is a bug in React." ); + } - break; + parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); + var _alternate = parentSuspense.alternate; + + if (_alternate !== null) { + _alternate.lanes = mergeLanes(_alternate.lanes, renderLanes); + } // This is intentionally passing this fiber as the parent + // because we want to schedule this fiber as having work + // on its children. We'll use the childLanes on + // this fiber to indicate that a context has changed. + + scheduleContextWorkOnParentPath( + parentSuspense, + renderLanes, + workInProgress + ); + nextFiber = fiber.sibling; + } else { + // Traverse down. + nextFiber = fiber.child; } - } else { - error( - "%s is not a supported value for revealOrder on . " + - 'Did you mean "together", "forwards" or "backwards"?', - revealOrder - ); + + if (nextFiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + nextFiber.return = fiber; + } else { + // No child. Traverse to next sibling. + nextFiber = fiber; + + while (nextFiber !== null) { + if (nextFiber === workInProgress) { + // We're back to the root of this subtree. Exit. + nextFiber = null; + break; + } + + var sibling = nextFiber.sibling; + + if (sibling !== null) { + // Set the return pointer of the sibling to the work-in-progress fiber. + sibling.return = nextFiber.return; + nextFiber = sibling; + break; + } // No more siblings. Traverse up. + + nextFiber = nextFiber.return; + } + } + + fiber = nextFiber; } } - } -} -function validateTailOptions(tailMode, revealOrder) { - { - if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) { - if (tailMode !== "collapsed" && tailMode !== "hidden") { - didWarnAboutTailOptions[tailMode] = true; + function propagateContextChanges( + workInProgress, + contexts, + renderLanes, + forcePropagateEntireTree + ) { + // Only used by lazy implementation + if (!enableLazyContextPropagation) { + return; + } - error( - '"%s" is not a supported value for tail on . ' + - 'Did you mean "collapsed" or "hidden"?', - tailMode - ); - } else if (revealOrder !== "forwards" && revealOrder !== "backwards") { - didWarnAboutTailOptions[tailMode] = true; + var fiber = workInProgress.child; - error( - ' is only valid if revealOrder is ' + - '"forwards" or "backwards". ' + - 'Did you mean to specify revealOrder="forwards"?', - tailMode - ); + if (fiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + fiber.return = workInProgress; } - } - } -} -function validateSuspenseListNestedChild(childSlot, index) { - { - var isAnArray = isArray(childSlot); - var isIterable = - !isAnArray && typeof getIteratorFn(childSlot) === "function"; - - if (isAnArray || isIterable) { - var type = isAnArray ? "array" : "iterable"; - - error( - "A nested %s was passed to row #%s in . Wrap it in " + - "an additional SuspenseList to configure its revealOrder: " + - " ... " + - "{%s} ... " + - "", - type, - index, - type - ); + while (fiber !== null) { + var nextFiber = void 0; // Visit this fiber. - return false; - } - } + var list = fiber.dependencies; - return true; -} + if (list !== null) { + nextFiber = fiber.child; + var dep = list.firstContext; -function validateSuspenseListChildren(children, revealOrder) { - { - if ( - (revealOrder === "forwards" || revealOrder === "backwards") && - children !== undefined && - children !== null && - children !== false - ) { - if (isArray(children)) { - for (var i = 0; i < children.length; i++) { - if (!validateSuspenseListNestedChild(children[i], i)) { - return; - } - } - } else { - var iteratorFn = getIteratorFn(children); + findChangedDep: while (dep !== null) { + // Assigning these to constants to help Flow + var dependency = dep; + var consumer = fiber; - if (typeof iteratorFn === "function") { - var childrenIterator = iteratorFn.call(children); + for (var i = 0; i < contexts.length; i++) { + var context = contexts[i]; // Check if the context matches. + // TODO: Compare selected values to bail out early. - if (childrenIterator) { - var step = childrenIterator.next(); - var _i = 0; + if (dependency.context === context) { + // Match! Schedule an update on this fiber. + // In the lazy implementation, don't mark a dirty flag on the + // dependency itself. Not all changes are propagated, so we can't + // rely on the propagation function alone to determine whether + // something has changed; the consumer will check. In the future, we + // could add back a dirty flag as an optimization to avoid double + // checking, but until we have selectors it's not really worth + // the trouble. + consumer.lanes = mergeLanes(consumer.lanes, renderLanes); + var alternate = consumer.alternate; - for (; !step.done; step = childrenIterator.next()) { - if (!validateSuspenseListNestedChild(step.value, _i)) { - return; - } + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); + } - _i++; + scheduleContextWorkOnParentPath( + consumer.return, + renderLanes, + workInProgress + ); + + if (!forcePropagateEntireTree) { + // During lazy propagation, when we find a match, we can defer + // propagating changes to the children, because we're going to + // visit them during render. We should continue propagating the + // siblings, though + nextFiber = null; + } // Since we already found a match, we can stop traversing the + // dependency list. + + break findChangedDep; + } } + + dep = dependency.next; } - } else { - error( - 'A single row was passed to a . ' + - "This is not useful since it needs multiple rows. " + - "Did you mean to pass multiple children or an array?", - revealOrder + } else if (fiber.tag === DehydratedFragment) { + // If a dehydrated suspense boundary is in this subtree, we don't know + // if it will have any context consumers in it. The best we can do is + // mark it as having updates. + var parentSuspense = fiber.return; + + if (parentSuspense === null) { + throw new Error( + "We just came from a parent so we must have had a parent. This is a bug in React." + ); + } + + parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); + var _alternate2 = parentSuspense.alternate; + + if (_alternate2 !== null) { + _alternate2.lanes = mergeLanes(_alternate2.lanes, renderLanes); + } // This is intentionally passing this fiber as the parent + // because we want to schedule this fiber as having work + // on its children. We'll use the childLanes on + // this fiber to indicate that a context has changed. + + scheduleContextWorkOnParentPath( + parentSuspense, + renderLanes, + workInProgress ); + nextFiber = null; + } else { + // Traverse down. + nextFiber = fiber.child; + } + + if (nextFiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + nextFiber.return = fiber; + } else { + // No child. Traverse to next sibling. + nextFiber = fiber; + + while (nextFiber !== null) { + if (nextFiber === workInProgress) { + // We're back to the root of this subtree. Exit. + nextFiber = null; + break; + } + + var sibling = nextFiber.sibling; + + if (sibling !== null) { + // Set the return pointer of the sibling to the work-in-progress fiber. + sibling.return = nextFiber.return; + nextFiber = sibling; + break; + } // No more siblings. Traverse up. + + nextFiber = nextFiber.return; + } } + + fiber = nextFiber; } } - } -} -function initSuspenseListRenderState( - workInProgress, - isBackwards, - tail, - lastContentRow, - tailMode -) { - var renderState = workInProgress.memoizedState; - - if (renderState === null) { - workInProgress.memoizedState = { - isBackwards: isBackwards, - rendering: null, - renderingStartTime: 0, - last: lastContentRow, - tail: tail, - tailMode: tailMode - }; - } else { - // We can reuse the existing object from previous renders. - renderState.isBackwards = isBackwards; - renderState.rendering = null; - renderState.renderingStartTime = 0; - renderState.last = lastContentRow; - renderState.tail = tail; - renderState.tailMode = tailMode; - } -} // This can end up rendering this component multiple passes. -// The first pass splits the children fibers into two sets. A head and tail. -// We first render the head. If anything is in fallback state, we do another -// pass through beginWork to rerender all children (including the tail) with -// the force suspend context. If the first render didn't have anything in -// in fallback state. Then we render each row in the tail one-by-one. -// That happens in the completeWork phase without going back to beginWork. - -function updateSuspenseListComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; - var revealOrder = nextProps.revealOrder; - var tailMode = nextProps.tail; - var newChildren = nextProps.children; - validateRevealOrder(revealOrder); - validateTailOptions(tailMode, revealOrder); - validateSuspenseListChildren(newChildren, revealOrder); - reconcileChildren(current, workInProgress, newChildren, renderLanes); - var suspenseContext = suspenseStackCursor.current; - var shouldForceFallback = hasSuspenseListContext( - suspenseContext, - ForceSuspenseFallback - ); - - if (shouldForceFallback) { - suspenseContext = setShallowSuspenseListContext( - suspenseContext, - ForceSuspenseFallback - ); - workInProgress.flags |= DidCapture; - } else { - var didSuspendBefore = - current !== null && (current.flags & DidCapture) !== NoFlags$1; - - if (didSuspendBefore) { - // If we previously forced a fallback, we need to schedule work - // on any nested boundaries to let them know to try to render - // again. This is the same as context updating. - propagateSuspenseContextChange( + function lazilyPropagateParentContextChanges( + current, + workInProgress, + renderLanes + ) { + var forcePropagateEntireTree = false; + propagateParentContextChanges( + current, workInProgress, - workInProgress.child, - renderLanes + renderLanes, + forcePropagateEntireTree ); - } - - suspenseContext = setDefaultShallowSuspenseListContext(suspenseContext); - } + } // Used for propagating a deferred tree (Suspense, Offscreen). We must propagate + // to the entire subtree, because we won't revisit it until after the current + // render has completed, at which point we'll have lost track of which providers + // have changed. - pushSuspenseListContext(workInProgress, suspenseContext); - - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - // In legacy mode, SuspenseList doesn't work so we just - // use make it a noop by treating it as the default revealOrder. - workInProgress.memoizedState = null; - } else { - switch (revealOrder) { - case "forwards": { - var lastContentRow = findLastContentRow(workInProgress.child); - var tail; + function propagateParentContextChangesToDeferredTree( + current, + workInProgress, + renderLanes + ) { + var forcePropagateEntireTree = true; + propagateParentContextChanges( + current, + workInProgress, + renderLanes, + forcePropagateEntireTree + ); + } - if (lastContentRow === null) { - // The whole list is part of the tail. - // TODO: We could fast path by just rendering the tail now. - tail = workInProgress.child; - workInProgress.child = null; - } else { - // Disconnect the tail rows after the content row. - // We're going to render them separately later. - tail = lastContentRow.sibling; - lastContentRow.sibling = null; + function propagateParentContextChanges( + current, + workInProgress, + renderLanes, + forcePropagateEntireTree + ) { + if (!enableLazyContextPropagation) { + return; + } // Collect all the parent providers that changed. Since this is usually small + // number, we use an Array instead of Set. + + var contexts = null; + var parent = workInProgress; + var isInsidePropagationBailout = false; + + while (parent !== null) { + if (!isInsidePropagationBailout) { + if ((parent.flags & NeedsPropagation) !== NoFlags$1) { + isInsidePropagationBailout = true; + } else if ((parent.flags & DidPropagateContext) !== NoFlags$1) { + break; + } } - initSuspenseListRenderState( - workInProgress, - false, // isBackwards - tail, - lastContentRow, - tailMode - ); - break; - } + if (parent.tag === ContextProvider) { + var currentParent = parent.alternate; - case "backwards": { - // We're going to find the first row that has existing content. - // At the same time we're going to reverse the list of everything - // we pass in the meantime. That's going to be our tail in reverse - // order. - var _tail = null; - var row = workInProgress.child; - workInProgress.child = null; + if (currentParent === null) { + throw new Error( + "Should have a current fiber. This is a bug in React." + ); + } - while (row !== null) { - var currentRow = row.alternate; // New rows can't be content rows. + var oldProps = currentParent.memoizedProps; - if (currentRow !== null && findFirstSuspended(currentRow) === null) { - // This is the beginning of the main content. - workInProgress.child = row; - break; - } + if (oldProps !== null) { + var providerType = parent.type; + var context = providerType._context; + var newProps = parent.pendingProps; + var newValue = newProps.value; + var oldValue = oldProps.value; - var nextRow = row.sibling; - row.sibling = _tail; - _tail = row; - row = nextRow; - } // TODO: If workInProgress.child is null, we can continue on the tail immediately. + if (!objectIs(newValue, oldValue)) { + if (contexts !== null) { + contexts.push(context); + } else { + contexts = [context]; + } + } + } + } - initSuspenseListRenderState( - workInProgress, - true, // isBackwards - _tail, - null, // last - tailMode - ); - break; + parent = parent.return; } - case "together": { - initSuspenseListRenderState( + if (contexts !== null) { + // If there were any changed providers, search through the children and + // propagate their changes. + propagateContextChanges( workInProgress, - false, // isBackwards - null, // tail - null, // last - undefined + contexts, + renderLanes, + forcePropagateEntireTree ); - break; - } + } // This is an optimization so that we only propagate once per subtree. If a + // deeply nested child bails out, and it calls this propagation function, it + // uses this flag to know that the remaining ancestor providers have already + // been propagated. + // + // NOTE: This optimization is only necessary because we sometimes enter the + // begin phase of nodes that don't have any work scheduled on them — + // specifically, the siblings of a node that _does_ have scheduled work. The + // siblings will bail out and call this function again, even though we already + // propagated content changes to it and its subtree. So we use this flag to + // mark that the parent providers already propagated. + // + // Unfortunately, though, we need to ignore this flag when we're inside a + // tree whose context propagation was deferred — that's what the + // `NeedsPropagation` flag is for. + // + // If we could instead bail out before entering the siblings' begin phase, + // then we could remove both `DidPropagateContext` and `NeedsPropagation`. + // Consider this as part of the next refactor to the fiber tree structure. - default: { - // The default reveal order is the same as not having - // a boundary. - workInProgress.memoizedState = null; - } + workInProgress.flags |= DidPropagateContext; } - } - - return workInProgress.child; -} - -function updatePortalComponent(current, workInProgress, renderLanes) { - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - var nextChildren = workInProgress.pendingProps; - - if (current === null) { - // Portals are special because we don't append the children during mount - // but at commit. Therefore we need to track insertions which the normal - // flow doesn't do during mount. This doesn't happen at the root because - // the root always starts with a "current" with a null child. - // TODO: Consider unifying this with how the root works. - workInProgress.child = reconcileChildFibers( - workInProgress, - null, - nextChildren, - renderLanes - ); - } else { - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - } - return workInProgress.child; -} + function checkIfContextChanged(currentDependencies) { + if (!enableLazyContextPropagation) { + return false; + } // Iterate over the current dependencies to see if something changed. This + // only gets called if props and state has already bailed out, so it's a + // relatively uncommon path, except at the root of a changed subtree. + // Alternatively, we could move these comparisons into `readContext`, but + // that's a much hotter path, so I think this is an appropriate trade off. -var hasWarnedAboutUsingNoValuePropOnContextProvider = false; + var dependency = currentDependencies.firstContext; -function updateContextProvider(current, workInProgress, renderLanes) { - var providerType = workInProgress.type; - var context = providerType._context; - var newProps = workInProgress.pendingProps; - var oldProps = workInProgress.memoizedProps; - var newValue = newProps.value; + while (dependency !== null) { + var context = dependency.context; + var newValue = context._currentValue2; + var oldValue = dependency.memoizedValue; - { - if (!("value" in newProps)) { - if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { - hasWarnedAboutUsingNoValuePropOnContextProvider = true; + if (!objectIs(newValue, oldValue)) { + return true; + } - error( - "The `value` prop is required for the ``. Did you misspell it or forget to pass it?" - ); + dependency = dependency.next; } - } - var providerPropTypes = workInProgress.type.propTypes; - - if (providerPropTypes) { - checkPropTypes(providerPropTypes, newProps, "prop", "Context.Provider"); + return false; } - } + function prepareToReadContext(workInProgress, renderLanes) { + currentlyRenderingFiber = workInProgress; + lastContextDependency = null; + lastFullyObservedContext = null; + var dependencies = workInProgress.dependencies; - pushProvider(workInProgress, context, newValue); + if (dependencies !== null) { + if (enableLazyContextPropagation) { + // Reset the work-in-progress list + dependencies.firstContext = null; + } else { + var firstContext = dependencies.firstContext; - if (enableLazyContextPropagation); - else { - if (oldProps !== null) { - var oldValue = oldProps.value; + if (firstContext !== null) { + if (includesSomeLane(dependencies.lanes, renderLanes)) { + // Context list has a pending update. Mark that this fiber performed work. + markWorkInProgressReceivedUpdate(); + } // Reset the work-in-progress list - if (objectIs(oldValue, newValue)) { - // No change. Bailout early if children are the same. - if (oldProps.children === newProps.children && !hasContextChanged()) { - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes - ); + dependencies.firstContext = null; + } } - } else { - // The context value changed. Search for matching consumers and schedule - // them to update. - propagateContextChange(workInProgress, context, renderLanes); } } - } - - var newChildren = newProps.children; - reconcileChildren(current, workInProgress, newChildren, renderLanes); - return workInProgress.child; -} - -var hasWarnedAboutUsingContextAsConsumer = false; - -function updateContextConsumer(current, workInProgress, renderLanes) { - var context = workInProgress.type; // The logic below for Context differs depending on PROD or DEV mode. In - // DEV mode, we create a separate object for Context.Consumer that acts - // like a proxy to Context. This proxy object adds unnecessary code in PROD - // so we use the old behaviour (Context.Consumer references Context) to - // reduce size and overhead. The separate object references context via - // a property called "_context", which also gives us the ability to check - // in DEV mode if this property exists or not and warn if it does not. - - { - if (context._context === undefined) { - // This may be because it's a Context (rather than a Consumer). - // Or it may be because it's older React where they're the same thing. - // We only want to warn if we're sure it's a new React. - if (context !== context.Consumer) { - if (!hasWarnedAboutUsingContextAsConsumer) { - hasWarnedAboutUsingContextAsConsumer = true; - + function readContext(context) { + { + // This warning would fire if you read context inside a Hook like useMemo. + // Unlike the class check below, it's not enforced in production for perf. + if (isDisallowedContextReadInDEV) { error( - "Rendering directly is not supported and will be removed in " + - "a future major release. Did you mean to render instead?" + "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()." ); } } - } else { - context = context._context; - } - } - - var newProps = workInProgress.pendingProps; - var render = newProps.children; - { - if (typeof render !== "function") { - 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." - ); + return readContextForConsumer(currentlyRenderingFiber, context); } - } - - prepareToReadContext(workInProgress, renderLanes); - var newValue = readContext(context); - - if (enableSchedulingProfiler) { - markComponentRenderStarted(workInProgress); - } - - var newChildren; - - { - ReactCurrentOwner$1.current = workInProgress; - setIsRendering(true); - newChildren = render(newValue); - setIsRendering(false); - } - - if (enableSchedulingProfiler) { - markComponentRenderStopped(); - } // React DevTools reads this flag. - - workInProgress.flags |= PerformedWork; - reconcileChildren(current, workInProgress, newChildren, renderLanes); - return workInProgress.child; -} - -function updateScopeComponent(current, workInProgress, renderLanes) { - var nextProps = workInProgress.pendingProps; - var nextChildren = nextProps.children; - reconcileChildren(current, workInProgress, nextChildren, renderLanes); - return workInProgress.child; -} - -function markWorkInProgressReceivedUpdate() { - didReceiveUpdate = true; -} -function checkIfWorkInProgressReceivedUpdate() { - return didReceiveUpdate; -} - -function resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress) { - if ((workInProgress.mode & ConcurrentMode) === NoMode) { - if (current !== null) { - // A lazy component only mounts if it suspended inside a non- - // concurrent tree, in an inconsistent state. We want to treat it like - // a new mount, even though an empty version of it already committed. - // Disconnect the alternate pointers. - current.alternate = null; - workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect + function readContextDuringReconcilation(consumer, context, renderLanes) { + if (currentlyRenderingFiber === null) { + prepareToReadContext(consumer, renderLanes); + } - workInProgress.flags |= Placement; + return readContextForConsumer(consumer, context); } - } -} -function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { - if (current !== null) { - // Reuse previous dependencies - workInProgress.dependencies = current.dependencies; - } + function readContextForConsumer(consumer, context) { + var value = context._currentValue2; - { - // Don't update "base" render times for bailouts. - stopProfilerTimerIfRunning(); - } + if (lastFullyObservedContext === context); + else { + var contextItem = { + context: context, + memoizedValue: value, + next: null + }; - markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. + if (lastContextDependency === null) { + if (consumer === null) { + 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()." + ); + } // This is the first dependency for this component. Create a new list. - if (!includesSomeLane(renderLanes, workInProgress.childLanes)) { - // The children don't have any work either. We can skip them. - // TODO: Once we add back resuming, we should check if the children are - // a work-in-progress set. If so, we need to transfer their effects. - if (enableLazyContextPropagation && current !== null) { - // Before bailing out, check if there are any context changes in - // the children. - lazilyPropagateParentContextChanges(current, workInProgress, renderLanes); + lastContextDependency = contextItem; + consumer.dependencies = { + lanes: NoLanes, + firstContext: contextItem + }; - if (!includesSomeLane(renderLanes, workInProgress.childLanes)) { - return null; + if (enableLazyContextPropagation) { + consumer.flags |= NeedsPropagation; + } + } else { + // Append a new context item. + lastContextDependency = lastContextDependency.next = contextItem; + } } - } else { - return null; - } - } // This fiber doesn't have work, but its subtree does. Clone the child - // fibers and continue. - - cloneChildFibers(current, workInProgress); - return workInProgress.child; -} -function remountFiber(current, oldWorkInProgress, newWorkInProgress) { - { - var returnFiber = oldWorkInProgress.return; + return value; + } - if (returnFiber === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Cannot swap the root fiber."); - } // Disconnect from the old current. - // It will get deleted. + // replace it with a lightweight shim that only has the features we use. - current.alternate = null; - oldWorkInProgress.alternate = null; // Connect to the new tree. + var AbortControllerLocal = + typeof AbortController !== "undefined" + ? AbortController // $FlowFixMe[missing-this-annot] + : // $FlowFixMe[prop-missing] + function AbortControllerShim() { + var listeners = []; + var signal = (this.signal = { + aborted: false, + addEventListener: function (type, listener) { + listeners.push(listener); + } + }); - newWorkInProgress.index = oldWorkInProgress.index; - newWorkInProgress.sibling = oldWorkInProgress.sibling; - newWorkInProgress.return = oldWorkInProgress.return; - newWorkInProgress.ref = oldWorkInProgress.ref; // Replace the child/sibling pointers above it. + this.abort = function () { + signal.aborted = true; + listeners.forEach(function (listener) { + return listener(); + }); + }; + }; // Intentionally not named imports because Rollup would + // use dynamic dispatch for CommonJS interop named imports. + + var scheduleCallback$1 = Scheduler.unstable_scheduleCallback, + NormalPriority = Scheduler.unstable_NormalPriority; + var CacheContext = { + $$typeof: REACT_CONTEXT_TYPE, + // We don't use Consumer/Provider for Cache components. So we'll cheat. + Consumer: null, + Provider: null, + // We'll initialize these at the root. + _currentValue: null, + _currentValue2: null, + _threadCount: 0, + _defaultValue: null, + _globalName: null + }; - if (oldWorkInProgress === returnFiber.child) { - returnFiber.child = newWorkInProgress; - } else { - var prevSibling = returnFiber.child; + { + CacheContext._currentRenderer = null; + CacheContext._currentRenderer2 = null; + } // Creates a new empty Cache instance with a ref-count of 0. The caller is responsible + // for retaining the cache once it is in use (retainCache), and releasing the cache + // once it is no longer needed (releaseCache). + + function createCache() { + var cache = { + controller: new AbortControllerLocal(), + data: new Map(), + refCount: 0 + }; + return cache; + } + function retainCache(cache) { + { + if (cache.controller.signal.aborted) { + warn( + "A cache instance was retained after it was already freed. " + + "This likely indicates a bug in React." + ); + } + } - if (prevSibling === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Expected parent to have a child."); - } // $FlowFixMe[incompatible-use] found when upgrading Flow + cache.refCount++; + } // Cleanup a cache instance, potentially freeing it if there are no more references - while (prevSibling.sibling !== oldWorkInProgress) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - prevSibling = prevSibling.sibling; + function releaseCache(cache) { + cache.refCount--; - if (prevSibling === null) { - // eslint-disable-next-line react-internal/prod-error-codes - throw new Error("Expected to find the previous sibling."); + { + if (cache.refCount < 0) { + warn( + "A cache instance was released after it was already freed. " + + "This likely indicates a bug in React." + ); } - } // $FlowFixMe[incompatible-use] found when upgrading Flow - - prevSibling.sibling = newWorkInProgress; - } // Delete the old fiber and place the new one. - // Since the old fiber is disconnected, we have to schedule it manually. - - var deletions = returnFiber.deletions; + } - if (deletions === null) { - returnFiber.deletions = [current]; - returnFiber.flags |= ChildDeletion; - } else { - deletions.push(current); + if (cache.refCount === 0) { + scheduleCallback$1(NormalPriority, function () { + cache.controller.abort(); + }); + } + } + function pushCacheProvider(workInProgress, cache) { + pushProvider(workInProgress, CacheContext, cache); + } + function popCacheProvider(workInProgress, cache) { + popProvider(CacheContext, workInProgress); } - newWorkInProgress.flags |= Placement; // Restart work from the new fiber. + var ReactCurrentBatchConfig$1 = + ReactSharedInternals.ReactCurrentBatchConfig; + var NoTransition = null; + function requestCurrentTransition() { + return ReactCurrentBatchConfig$1.transition; + } // When retrying a Suspense/Offscreen boundary, we restore the cache that was + // used during the previous render by placing it here, on the stack. - return newWorkInProgress; - } -} + var resumedCache = createCursor(null); // During the render/synchronous commit phase, we don't actually process the + // transitions. Therefore, we want to lazily combine transitions. Instead of + // comparing the arrays of transitions when we combine them and storing them + // and filtering out the duplicates, we will instead store the unprocessed transitions + // in an array and actually filter them in the passive phase. -function checkScheduledUpdateOrContext(current, renderLanes) { - // Before performing an early bailout, we must check if there are pending - // updates or context. - var updateLanes = current.lanes; + var transitionStack = createCursor(null); - if (includesSomeLane(updateLanes, renderLanes)) { - return true; - } // No pending update, but because context is propagated lazily, we need - // to check for a context change before we bail out. + function peekCacheFromPool() { + // If we're rendering inside a Suspense boundary that is currently hidden, + // we should use the same cache that we used during the previous render, if + // one exists. - if (enableLazyContextPropagation) { - var dependencies = current.dependencies; + var cacheResumedFromPreviousRender = resumedCache.current; - if (dependencies !== null && checkIfContextChanged(dependencies)) { - return true; - } - } + if (cacheResumedFromPreviousRender !== null) { + return cacheResumedFromPreviousRender; + } // Otherwise, check the root's cache pool. - return false; -} + var root = getWorkInProgressRoot(); + var cacheFromRootCachePool = root.pooledCache; + return cacheFromRootCachePool; + } + + function requestCacheFromPool(renderLanes) { + // Similar to previous function, except if there's not already a cache in the + // pool, we allocate a new one. + var cacheFromPool = peekCacheFromPool(); + + if (cacheFromPool !== null) { + return cacheFromPool; + } // Create a fresh cache and add it to the root cache pool. A cache can have + // multiple owners: + // - A cache pool that lives on the FiberRoot. This is where all fresh caches + // are originally created (TODO: except during refreshes, until we implement + // this correctly). The root takes ownership immediately when the cache is + // created. Conceptually, root.pooledCache is an Option> (owned), + // and the return value of this function is a &Arc (borrowed). + // - One of several fiber types: host root, cache boundary, suspense + // component. These retain and release in the commit phase. -function attemptEarlyBailoutIfNoScheduledUpdate( - current, - workInProgress, - renderLanes -) { - // This fiber does not have any pending work. Bailout without entering - // the begin phase. There's still some bookkeeping we that needs to be done - // in this optimized path, mostly pushing stuff onto the stack. - switch (workInProgress.tag) { - case HostRoot: - pushHostRootContext(workInProgress); - pushRootTransition(workInProgress); + var root = getWorkInProgressRoot(); + var freshCache = createCache(); + root.pooledCache = freshCache; + retainCache(freshCache); - if (enableTransitionTracing) { - pushRootMarkerInstance(workInProgress); + if (freshCache !== null) { + root.pooledCacheLanes |= renderLanes; } - { - var cache = current.memoizedState.cache; - pushCacheProvider(workInProgress, cache); + return freshCache; + } + function pushRootTransition(workInProgress, root, renderLanes) { + if (enableTransitionTracing) { + var rootTransitions = getWorkInProgressTransitions(); + push(transitionStack, rootTransitions, workInProgress); } - break; - - case HostSingleton: - case HostComponent: - pushHostContext(workInProgress); - break; - - case ClassComponent: { - break; } - - case HostPortal: - pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); - break; - - case ContextProvider: { - var newValue = workInProgress.memoizedProps.value; - var context = workInProgress.type._context; - pushProvider(workInProgress, context, newValue); - break; + function popRootTransition(workInProgress, root, renderLanes) { + if (enableTransitionTracing) { + pop(transitionStack, workInProgress); + } } - - case Profiler: + function pushTransition( + offscreenWorkInProgress, + prevCachePool, + newTransitions + ) { { - // Profiler should only call onRender when one of its descendants actually rendered. - var hasChildWork = includesSomeLane( - renderLanes, - workInProgress.childLanes - ); - - if (hasChildWork) { - workInProgress.flags |= Update; - } - - { - // Reset effect durations for the next eventual effect phase. - // These are reset during render to allow the DevTools commit hook a chance to read them, - var stateNode = workInProgress.stateNode; - stateNode.effectDuration = 0; - stateNode.passiveEffectDuration = 0; + if (prevCachePool === null) { + push(resumedCache, resumedCache.current, offscreenWorkInProgress); + } else { + push(resumedCache, prevCachePool.pool, offscreenWorkInProgress); } } - break; - - case SuspenseComponent: { - var state = workInProgress.memoizedState; - - if (state !== null) { - if (state.dehydrated !== null) { - // We're not going to render the children, so this is just to maintain - // push/pop symmetry - pushPrimaryTreeSuspenseHandler(workInProgress); // We know that this component will suspend again because if it has - // been unsuspended it has committed as a resolved Suspense component. - // If it needs to be retried, it should have work scheduled on it. - - workInProgress.flags |= DidCapture; // We should never render the children of a dehydrated boundary until we - // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork. - - return null; - } // If this boundary is currently timed out, we need to decide - // whether to retry the primary children, or to skip over it and - // go straight to the fallback. Check the priority of the primary - // child fragment. - - var primaryChildFragment = workInProgress.child; - var primaryChildLanes = primaryChildFragment.childLanes; - - if (includesSomeLane(renderLanes, primaryChildLanes)) { - // The primary children have pending work. Use the normal path - // to attempt to render the primary children again. - return updateSuspenseComponent(current, workInProgress, renderLanes); + if (enableTransitionTracing) { + if (transitionStack.current === null) { + push(transitionStack, newTransitions, offscreenWorkInProgress); + } else if (newTransitions === null) { + push( + transitionStack, + transitionStack.current, + offscreenWorkInProgress + ); } else { - // The primary child fragment does not have pending work marked - // on it - pushPrimaryTreeSuspenseHandler(workInProgress); // The primary children do not have pending work with sufficient - // priority. Bailout. - - var child = bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderLanes + push( + transitionStack, + transitionStack.current.concat(newTransitions), + offscreenWorkInProgress ); - - if (child !== null) { - // The fallback children have pending work. Skip over the - // primary children and work on the fallback. - return child.sibling; - } else { - // Note: We can return `null` here because we already checked - // whether there were nested context consumers, via the call to - // `bailoutOnAlreadyFinishedWork` above. - return null; - } } - } else { - pushPrimaryTreeSuspenseHandler(workInProgress); } - - break; } + function popTransition(workInProgress, current) { + if (current !== null) { + if (enableTransitionTracing) { + pop(transitionStack, workInProgress); + } - case SuspenseListComponent: { - var didSuspendBefore = (current.flags & DidCapture) !== NoFlags$1; - - var _hasChildWork = includesSomeLane( - renderLanes, - workInProgress.childLanes - ); - - if (enableLazyContextPropagation && !_hasChildWork) { - // Context changes may not have been propagated yet. We need to do - // that now, before we can decide whether to bail out. - // TODO: We use `childLanes` as a heuristic for whether there is - // remaining work in a few places, including - // `bailoutOnAlreadyFinishedWork` and - // `updateDehydratedSuspenseComponent`. We should maybe extract this - // into a dedicated function. - lazilyPropagateParentContextChanges( - current, - workInProgress, - renderLanes - ); - _hasChildWork = includesSomeLane( - renderLanes, - workInProgress.childLanes - ); + { + pop(resumedCache, workInProgress); + } + } + } + function getPendingTransitions() { + if (!enableTransitionTracing) { + return null; } - if (didSuspendBefore) { - if (_hasChildWork) { - // If something was in fallback state last time, and we have all the - // same children then we're still in progressive loading state. - // Something might get unblocked by state updates or retries in the - // tree which will affect the tail. So we need to use the normal - // path to compute the correct tail. - return updateSuspenseListComponent( - current, - workInProgress, - renderLanes - ); - } // If none of the children had any work, that means that none of - // them got retried so they'll still be blocked in the same way - // as before. We can fast bail out. - - workInProgress.flags |= DidCapture; - } // If nothing suspended before and we're rendering the same children, - // then the tail doesn't matter. Anything new that suspends will work - // in the "together" mode, so we can continue from the state we had. + return transitionStack.current; + } + function getSuspendedCache() { + // cache that would have been used to render fresh data during this render, + // if there was any, so that we can resume rendering with the same cache when + // we receive more data. - var renderState = workInProgress.memoizedState; + var cacheFromPool = peekCacheFromPool(); - if (renderState !== null) { - // Reset to the "together" mode in case we've started a different - // update in the past but didn't complete it. - renderState.rendering = null; - renderState.tail = null; - renderState.lastEffect = null; + if (cacheFromPool === null) { + return null; } - pushSuspenseListContext(workInProgress, suspenseStackCursor.current); + return { + // We must also save the parent, so that when we resume we can detect + // a refresh. + parent: CacheContext._currentValue2, + pool: cacheFromPool + }; + } + function getOffscreenDeferredCache() { + var cacheFromPool = peekCacheFromPool(); - if (_hasChildWork) { - break; - } else { - // If none of the children had any work, that means that none of - // them got retried so they'll still be blocked in the same way - // as before. We can fast bail out. + if (cacheFromPool === null) { return null; } + + return { + // We must also store the parent, so that when we resume we can detect + // a refresh. + parent: CacheContext._currentValue2, + pool: cacheFromPool + }; } - case OffscreenComponent: - case LegacyHiddenComponent: { - // Need to check if the tree still needs to be deferred. This is - // almost identical to the logic used in the normal update path, - // so we'll just enter that. The only difference is we'll bail out - // at the next level instead of this one, because the child props - // have not changed. Which is fine. - // TODO: Probably should refactor `beginWork` to split the bailout - // path from the normal path. I'm tempted to do a labeled break here - // but I won't :) - workInProgress.lanes = NoLanes; - return updateOffscreenComponent(current, workInProgress, renderLanes); + function getSuspenseFallbackChild(fiber) { + return fiber.child.sibling.child; } - case CacheComponent: { + var emptyObject = {}; + + function collectScopedNodes(node, fn, scopedNodes) { { - var _cache = current.memoizedState.cache; - pushCacheProvider(workInProgress, _cache); - } + if (node.tag === HostComponent) { + var type = node.type, + memoizedProps = node.memoizedProps, + stateNode = node.stateNode; + var instance = getPublicInstance(stateNode); - break; - } + if ( + instance !== null && + fn(type, memoizedProps || emptyObject, instance) === true + ) { + scopedNodes.push(instance); + } + } - case TracingMarkerComponent: { - if (enableTransitionTracing) { - var instance = workInProgress.stateNode; + var child = node.child; - if (instance !== null) { - pushMarkerInstance(workInProgress, instance); + if (isFiberSuspenseAndTimedOut(node)) { + child = getSuspenseFallbackChild(node); } - } - } - } - - return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); -} -function beginWork$1(current, workInProgress, renderLanes) { - { - if (workInProgress._debugNeedsRemount && current !== null) { - // This will restart the begin phase with a new fiber. - return remountFiber( - current, - workInProgress, - createFiberFromTypeAndProps( - workInProgress.type, - workInProgress.key, - workInProgress.pendingProps, - workInProgress._debugSource || null, - workInProgress._debugOwner || null, - workInProgress.mode, - workInProgress.lanes - ) - ); + if (child !== null) { + collectScopedNodesFromChildren(child, fn, scopedNodes); + } + } } - } - if (current !== null) { - var oldProps = current.memoizedProps; - var newProps = workInProgress.pendingProps; + function collectFirstScopedNode(node, fn) { + { + if (node.tag === HostComponent) { + var type = node.type, + memoizedProps = node.memoizedProps, + stateNode = node.stateNode; + var instance = getPublicInstance(stateNode); + + if (instance !== null && fn(type, memoizedProps, instance) === true) { + return instance; + } + } - if ( - oldProps !== newProps || - hasContextChanged() || // Force a re-render if the implementation changed due to hot reload: - workInProgress.type !== current.type - ) { - // If props or context changed, mark the fiber as having performed work. - // This may be unset if the props are determined to be equal later (memo). - didReceiveUpdate = true; - } else { - // Neither props nor legacy context changes. Check if there's a pending - // update or context change. - var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext( - current, - renderLanes - ); + var child = node.child; - if ( - !hasScheduledUpdateOrContext && // If this is the second pass of an error or suspense boundary, there - // may not be work scheduled on `current`, so we check for this flag. - (workInProgress.flags & DidCapture) === NoFlags$1 - ) { - // No pending updates or context. Bail out now. - didReceiveUpdate = false; - return attemptEarlyBailoutIfNoScheduledUpdate( - current, - workInProgress, - renderLanes - ); - } + if (isFiberSuspenseAndTimedOut(node)) { + child = getSuspenseFallbackChild(node); + } - if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags$1) { - // This is a special case that only exists for legacy mode. - // See https://github.com/facebook/react/pull/19216. - didReceiveUpdate = true; - } else { - // An update was scheduled on this fiber, but there are no new props - // nor legacy context. Set this to false. If an update queue or context - // consumer produces a changed value, it will set this to true. Otherwise, - // the component will assume the children have not changed and bail out. - didReceiveUpdate = false; + if (child !== null) { + return collectFirstScopedNodeFromChildren(child, fn); + } } - } - } else { - didReceiveUpdate = false; - } // Before entering the begin phase, clear pending update priority. - // TODO: This assumes that we're about to evaluate the component and process - // the update queue. However, there's an exception: SimpleMemoComponent - // sometimes bails out later in the begin phase. This indicates that we should - // move this assignment out of the common path and into each branch. - workInProgress.lanes = NoLanes; - - switch (workInProgress.tag) { - case IndeterminateComponent: { - return mountIndeterminateComponent( - current, - workInProgress, - workInProgress.type, - renderLanes - ); + return null; } - case LazyComponent: { - var elementType = workInProgress.elementType; - return mountLazyComponent( - current, - workInProgress, - elementType, - renderLanes - ); - } + function collectScopedNodesFromChildren(startingChild, fn, scopedNodes) { + var child = startingChild; - case FunctionComponent: { - var Component = workInProgress.type; - var unresolvedProps = workInProgress.pendingProps; - var resolvedProps = - workInProgress.elementType === Component - ? unresolvedProps - : resolveDefaultProps(Component, unresolvedProps); - return updateFunctionComponent( - current, - workInProgress, - Component, - resolvedProps, - renderLanes - ); + while (child !== null) { + collectScopedNodes(child, fn, scopedNodes); + child = child.sibling; + } } - case ClassComponent: { - var _Component = workInProgress.type; - var _unresolvedProps = workInProgress.pendingProps; + function collectFirstScopedNodeFromChildren(startingChild, fn) { + var child = startingChild; - var _resolvedProps = - workInProgress.elementType === _Component - ? _unresolvedProps - : resolveDefaultProps(_Component, _unresolvedProps); + while (child !== null) { + var scopedNode = collectFirstScopedNode(child, fn); - return updateClassComponent( - current, - workInProgress, - _Component, - _resolvedProps, - renderLanes - ); - } + if (scopedNode !== null) { + return scopedNode; + } - case HostRoot: - return updateHostRoot(current, workInProgress, renderLanes); + child = child.sibling; + } - case HostHoistable: + return null; + } - // Fall through + function collectNearestContextValues(node, context, childContextValues) { + if (node.tag === ContextProvider && node.type._context === context) { + var contextValue = node.memoizedProps.value; + childContextValues.push(contextValue); + } else { + var child = node.child; - case HostSingleton: + if (isFiberSuspenseAndTimedOut(node)) { + child = getSuspenseFallbackChild(node); + } - // Fall through + if (child !== null) { + collectNearestChildContextValues(child, context, childContextValues); + } + } + } - case HostComponent: - return updateHostComponent$1(current, workInProgress, renderLanes); + function collectNearestChildContextValues( + startingChild, + context, + childContextValues + ) { + var child = startingChild; - case HostText: - return updateHostText$1(); + while (child !== null) { + collectNearestContextValues(child, context, childContextValues); + child = child.sibling; + } + } - case SuspenseComponent: - return updateSuspenseComponent(current, workInProgress, renderLanes); + function DO_NOT_USE_queryAllNodes(fn) { + var currentFiber = getInstanceFromScope(); - case HostPortal: - return updatePortalComponent(current, workInProgress, renderLanes); + if (currentFiber === null) { + return null; + } - case ForwardRef: { - var type = workInProgress.type; - var _unresolvedProps2 = workInProgress.pendingProps; + var child = currentFiber.child; + var scopedNodes = []; - var _resolvedProps2 = - workInProgress.elementType === type - ? _unresolvedProps2 - : resolveDefaultProps(type, _unresolvedProps2); + if (child !== null) { + collectScopedNodesFromChildren(child, fn, scopedNodes); + } - return updateForwardRef( - current, - workInProgress, - type, - _resolvedProps2, - renderLanes - ); + return scopedNodes.length === 0 ? null : scopedNodes; } - case Fragment: - return updateFragment(current, workInProgress, renderLanes); - - case Mode: - return updateMode(current, workInProgress, renderLanes); + function DO_NOT_USE_queryFirstNode(fn) { + var currentFiber = getInstanceFromScope(); - case Profiler: - return updateProfiler(current, workInProgress, renderLanes); - - case ContextProvider: - return updateContextProvider(current, workInProgress, renderLanes); + if (currentFiber === null) { + return null; + } - case ContextConsumer: - return updateContextConsumer(current, workInProgress, renderLanes); + var child = currentFiber.child; - case MemoComponent: { - var _type2 = workInProgress.type; - var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. + if (child !== null) { + return collectFirstScopedNodeFromChildren(child, fn); + } - var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); + return null; + } - { - if (workInProgress.type !== workInProgress.elementType) { - var outerPropTypes = _type2.propTypes; + function containsNode(node) { + var fiber = getInstanceFromNode(); - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - _resolvedProps3, // Resolved for outer only - "prop", - getComponentNameFromType(_type2) - ); - } + while (fiber !== null) { + if (fiber.tag === ScopeComponent && fiber.stateNode === this) { + return true; } + + fiber = fiber.return; } - _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); - return updateMemoComponent( - current, - workInProgress, - _type2, - _resolvedProps3, - renderLanes - ); + return false; } - case SimpleMemoComponent: { - return updateSimpleMemoComponent( - current, - workInProgress, - workInProgress.type, - workInProgress.pendingProps, - renderLanes - ); - } + function getChildContextValues(context) { + var currentFiber = getInstanceFromScope(); - case IncompleteClassComponent: { - var _Component2 = workInProgress.type; - var _unresolvedProps4 = workInProgress.pendingProps; + if (currentFiber === null) { + return []; + } - var _resolvedProps4 = - workInProgress.elementType === _Component2 - ? _unresolvedProps4 - : resolveDefaultProps(_Component2, _unresolvedProps4); + var child = currentFiber.child; + var childContextValues = []; - return mountIncompleteClassComponent( - current, - workInProgress, - _Component2, - _resolvedProps4, - renderLanes - ); + if (child !== null) { + collectNearestChildContextValues(child, context, childContextValues); + } + + return childContextValues; } - case SuspenseListComponent: { - return updateSuspenseListComponent(current, workInProgress, renderLanes); + function createScopeInstance() { + return { + DO_NOT_USE_queryAllNodes: DO_NOT_USE_queryAllNodes, + DO_NOT_USE_queryFirstNode: DO_NOT_USE_queryFirstNode, + containsNode: containsNode, + getChildContextValues: getChildContextValues + }; } - case ScopeComponent: { - { - return updateScopeComponent(current, workInProgress, renderLanes); - } + function markUpdate(workInProgress) { + // Tag the fiber with an update effect. This turns a Placement into + // a PlacementAndUpdate. + workInProgress.flags |= Update; } - case OffscreenComponent: { - return updateOffscreenComponent(current, workInProgress, renderLanes); + function markRef(workInProgress) { + workInProgress.flags |= Ref | RefStatic; } - case LegacyHiddenComponent: { + function appendAllChildren( + parent, + workInProgress, + needsVisibilityToggle, + isHidden + ) { { - return updateLegacyHiddenComponent( - current, - workInProgress, - renderLanes - ); + // We only have the top Fiber that was created but we need recurse down its + // children to find all the terminal nodes. + var node = workInProgress.child; + + while (node !== null) { + if (node.tag === HostComponent || node.tag === HostText) { + appendInitialChild(parent, node.stateNode); + } else if (node.tag === HostPortal || false); + else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } + + if (node === workInProgress) { + return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow + + while (node.sibling === null) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + if (node.return === null || node.return === workInProgress) { + return; + } + + node = node.return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow + + node.sibling.return = node.return; + node = node.sibling; + } } - } + } // An unfortunate fork of appendAllChildren because we have two different parent types. - case CacheComponent: { + function updateHostComponent( + current, + workInProgress, + type, + newProps, + renderLanes + ) { { - return updateCacheComponent(current, workInProgress, renderLanes); + // If we have an alternate, that means this is an update and we need to + // schedule a side-effect to do the updates. + var oldProps = current.memoizedProps; + + if (oldProps === newProps) { + // In mutation mode, this is sufficient for a bailout because + // we won't touch this node even if children changed. + return; + } + + markUpdate(workInProgress); } + } // This function must be called at the very end of the complete phase, because + // it might throw to suspend, and if the resource immediately loads, the work + // loop will resume rendering as if the work-in-progress completed. So it must + // fully complete. + // TODO: This should ideally move to begin phase, but currently the instance is + // not created until the complete phase. For our existing use cases, host nodes + // that suspend don't have children, so it doesn't matter. But that might not + // always be true in the future. + + function preloadInstanceAndSuspendIfNeeded( + workInProgress, + type, + props, + renderLanes + ) { + { + // If this flag was set previously, we can remove it. The flag + // represents whether this particular set of props might ever need to + // suspend. The safest thing to do is for maySuspendCommit to always + // return true, but if the renderer is reasonably confident that the + // underlying resource won't be evicted, it can return false as a + // performance optimization. + workInProgress.flags &= ~MaySuspendCommit; + return; + } // Mark this fiber with a flag. This gets set on all host instances } - case TracingMarkerComponent: { - if (enableTransitionTracing) { - return updateTracingMarkerComponent( - current, - workInProgress, - renderLanes - ); - } + function scheduleRetryEffect(workInProgress, retryQueue) { + var wakeables = retryQueue; - break; + if (wakeables !== null) { + // Schedule an effect to attach a retry listener to the promise. + // TODO: Move to passive phase + workInProgress.flags |= Update; + } else { + // This boundary suspended, but no wakeables were added to the retry + // queue. Check if the renderer suspended commit. If so, this means + // that once the fallback is committed, we can immediately retry + // rendering again, because rendering wasn't actually blocked. Only + // the commit phase. + // TODO: Consider a model where we always schedule an immediate retry, even + // for normal Suspense. That way the retry can partially render up to the + // first thing that suspends. + if (workInProgress.flags & ScheduleRetry) { + var retryLane = // TODO: This check should probably be moved into claimNextRetryLane + // I also suspect that we need some further consolidation of offscreen + // and retry lanes. + workInProgress.tag !== OffscreenComponent + ? claimNextRetryLane() + : OffscreenLane; + workInProgress.lanes = mergeLanes(workInProgress.lanes, retryLane); + } + } + } + + function updateHostText(current, workInProgress, oldText, newText) { + { + // If the text differs, mark it as an update. All the work in done in commitWork. + if (oldText !== newText) { + markUpdate(workInProgress); + } + } } - } - throw new Error( - "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in " + - "React. Please file an issue." - ); -} + function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { + switch (renderState.tailMode) { + case "hidden": { + // Any insertions at the end of the tail list after this point + // should be invisible. If there are already mounted boundaries + // anything before them are not considered for collapsing. + // Therefore we need to go through the whole tail to find if + // there are any. + var tailNode = renderState.tail; + var lastTailNode = null; -var valueCursor = createCursor(null); + while (tailNode !== null) { + if (tailNode.alternate !== null) { + lastTailNode = tailNode; + } -var renderer2CursorDEV; + tailNode = tailNode.sibling; + } // Next we're simply going to delete all insertions after the + // last rendered item. -{ - renderer2CursorDEV = createCursor(null); -} + if (lastTailNode === null) { + // All remaining items in the tail are insertions. + renderState.tail = null; + } else { + // Detach the insertion after the last node that was already + // inserted. + lastTailNode.sibling = null; + } -var rendererSigil; + break; + } -{ - // Use this to detect multiple renderers using the same context - rendererSigil = {}; -} + case "collapsed": { + // Any insertions at the end of the tail list after this point + // should be invisible. If there are already mounted boundaries + // anything before them are not considered for collapsing. + // Therefore we need to go through the whole tail to find if + // there are any. + var _tailNode = renderState.tail; + var _lastTailNode = null; -var currentlyRenderingFiber = null; -var lastContextDependency = null; -var lastFullyObservedContext = null; -var isDisallowedContextReadInDEV = false; -function resetContextDependencies() { - // This is called right before React yields execution, to ensure `readContext` - // cannot be called outside the render phase. - currentlyRenderingFiber = null; - lastContextDependency = null; - lastFullyObservedContext = null; - - { - isDisallowedContextReadInDEV = false; - } -} -function enterDisallowedContextReadInDEV() { - { - isDisallowedContextReadInDEV = true; - } -} -function exitDisallowedContextReadInDEV() { - { - isDisallowedContextReadInDEV = false; - } -} -function pushProvider(providerFiber, context, nextValue) { - { - push(valueCursor, context._currentValue2, providerFiber); - context._currentValue2 = nextValue; + while (_tailNode !== null) { + if (_tailNode.alternate !== null) { + _lastTailNode = _tailNode; + } - { - push(renderer2CursorDEV, context._currentRenderer2, providerFiber); + _tailNode = _tailNode.sibling; + } // Next we're simply going to delete all insertions after the + // last rendered item. - if ( - context._currentRenderer2 !== undefined && - context._currentRenderer2 !== null && - context._currentRenderer2 !== rendererSigil - ) { - error( - "Detected multiple renderers concurrently rendering the " + - "same context provider. This is currently unsupported." - ); - } + if (_lastTailNode === null) { + // All remaining items in the tail are insertions. + if (!hasRenderedATailFallback && renderState.tail !== null) { + // We suspended during the head. We want to show at least one + // row at the tail. So we'll keep on and cut off the rest. + renderState.tail.sibling = null; + } else { + renderState.tail = null; + } + } else { + // Detach the insertion after the last node that was already + // inserted. + _lastTailNode.sibling = null; + } - context._currentRenderer2 = rendererSigil; + break; + } + } } - } -} -function popProvider(context, providerFiber) { - var currentValue = valueCursor.current; - { - { - context._currentValue2 = currentValue; - } + function bubbleProperties(completedWork) { + var didBailout = + completedWork.alternate !== null && + completedWork.alternate.child === completedWork.child; + var newChildLanes = NoLanes; + var subtreeFlags = NoFlags$1; - { - var currentRenderer2 = renderer2CursorDEV.current; - pop(renderer2CursorDEV, providerFiber); - context._currentRenderer2 = currentRenderer2; - } - } + if (!didBailout) { + // Bubble up the earliest expiration time. + if ((completedWork.mode & ProfileMode) !== NoMode) { + // In profiling mode, resetChildExpirationTime is also used to reset + // profiler durations. + var actualDuration = completedWork.actualDuration; + var treeBaseDuration = completedWork.selfBaseDuration; + var child = completedWork.child; - pop(valueCursor, providerFiber); -} -function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { - // Update the child lanes of all the ancestors, including the alternates. - var node = parent; + while (child !== null) { + newChildLanes = mergeLanes( + newChildLanes, + mergeLanes(child.lanes, child.childLanes) + ); + subtreeFlags |= child.subtreeFlags; + subtreeFlags |= child.flags; // When a fiber is cloned, its actualDuration is reset to 0. This value will + // only be updated if work is done on the fiber (i.e. it doesn't bailout). + // When work is done, it should bubble to the parent's actualDuration. If + // the fiber has not been cloned though, (meaning no work was done), then + // this value will reflect the amount of time spent working on a previous + // render. In that case it should not bubble. We determine whether it was + // cloned by comparing the child pointer. + // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + + actualDuration += child.actualDuration; // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + + treeBaseDuration += child.treeBaseDuration; + child = child.sibling; + } - while (node !== null) { - var alternate = node.alternate; + completedWork.actualDuration = actualDuration; + completedWork.treeBaseDuration = treeBaseDuration; + } else { + var _child = completedWork.child; - if (!isSubsetOfLanes(node.childLanes, renderLanes)) { - node.childLanes = mergeLanes(node.childLanes, renderLanes); + while (_child !== null) { + newChildLanes = mergeLanes( + newChildLanes, + mergeLanes(_child.lanes, _child.childLanes) + ); + subtreeFlags |= _child.subtreeFlags; + subtreeFlags |= _child.flags; // Update the return pointer so the tree is consistent. This is a code + // smell because it assumes the commit phase is never concurrent with + // the render phase. Will address during refactor to alternate model. - if (alternate !== null) { - alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); - } - } else if ( - alternate !== null && - !isSubsetOfLanes(alternate.childLanes, renderLanes) - ) { - alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); - } else; + _child.return = completedWork; + _child = _child.sibling; + } + } - if (node === propagationRoot) { - break; - } + completedWork.subtreeFlags |= subtreeFlags; + } else { + // Bubble up the earliest expiration time. + if ((completedWork.mode & ProfileMode) !== NoMode) { + // In profiling mode, resetChildExpirationTime is also used to reset + // profiler durations. + var _treeBaseDuration = completedWork.selfBaseDuration; + var _child2 = completedWork.child; + + while (_child2 !== null) { + newChildLanes = mergeLanes( + newChildLanes, + mergeLanes(_child2.lanes, _child2.childLanes) + ); // "Static" flags share the lifetime of the fiber/hook they belong to, + // so we should bubble those up even during a bailout. All the other + // flags have a lifetime only of a single render + commit, so we should + // ignore them. + + subtreeFlags |= _child2.subtreeFlags & StaticMask; + subtreeFlags |= _child2.flags & StaticMask; // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + + _treeBaseDuration += _child2.treeBaseDuration; + _child2 = _child2.sibling; + } + + completedWork.treeBaseDuration = _treeBaseDuration; + } else { + var _child3 = completedWork.child; + + while (_child3 !== null) { + newChildLanes = mergeLanes( + newChildLanes, + mergeLanes(_child3.lanes, _child3.childLanes) + ); // "Static" flags share the lifetime of the fiber/hook they belong to, + // so we should bubble those up even during a bailout. All the other + // flags have a lifetime only of a single render + commit, so we should + // ignore them. + + subtreeFlags |= _child3.subtreeFlags & StaticMask; + subtreeFlags |= _child3.flags & StaticMask; // Update the return pointer so the tree is consistent. This is a code + // smell because it assumes the commit phase is never concurrent with + // the render phase. Will address during refactor to alternate model. + + _child3.return = completedWork; + _child3 = _child3.sibling; + } + } - node = node.return; - } + completedWork.subtreeFlags |= subtreeFlags; + } - { - if (node !== propagationRoot) { - 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." - ); + completedWork.childLanes = newChildLanes; + return didBailout; } - } -} -function propagateContextChange(workInProgress, context, renderLanes) { - if (enableLazyContextPropagation) { - // TODO: This path is only used by Cache components. Update - // lazilyPropagateParentContextChanges to look for Cache components so they - // can take advantage of lazy propagation. - var forcePropagateEntireTree = true; - propagateContextChanges( + + function completeDehydratedSuspenseBoundary( + current, workInProgress, - [context], - renderLanes, - forcePropagateEntireTree - ); - } else { - propagateContextChange_eager(workInProgress, context, renderLanes); - } -} + nextState + ) { + var wasHydrated = popHydrationState(); -function propagateContextChange_eager(workInProgress, context, renderLanes) { - // Only used by eager implementation - if (enableLazyContextPropagation) { - return; - } + if (nextState !== null && nextState.dehydrated !== null) { + // We might be inside a hydration state the first time we're picking up this + // Suspense boundary, and also after we've reentered it for further hydration. + if (current === null) { + if (!wasHydrated) { + throw new Error( + "A dehydrated suspense component was completed without a hydrated node. " + + "This is probably a bug in React." + ); + } - var fiber = workInProgress.child; + prepareToHydrateHostSuspenseInstance(); + bubbleProperties(workInProgress); - if (fiber !== null) { - // Set the return pointer of the child to the work-in-progress fiber. - fiber.return = workInProgress; - } + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + var isTimedOutSuspense = nextState !== null; - while (fiber !== null) { - var nextFiber = void 0; // Visit this fiber. + if (isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var primaryChildFragment = workInProgress.child; - var list = fiber.dependencies; + if (primaryChildFragment !== null) { + // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + primaryChildFragment.treeBaseDuration; + } + } + } + } - if (list !== null) { - nextFiber = fiber.child; - var dependency = list.firstContext; + return false; + } else { + if ((workInProgress.flags & DidCapture) === NoFlags$1) { + // This boundary did not suspend so it's now hydrated and unsuspended. + workInProgress.memoizedState = null; + } // If nothing suspended, we need to schedule an effect to mark this boundary + // as having hydrated so events know that they're free to be invoked. + // It's also a signal to replay events and the suspense callback. + // If something suspended, schedule an effect to attach retry listeners. + // So we might as well always mark this. - while (dependency !== null) { - // Check if the context matches. - if (dependency.context === context) { - // Match! Schedule an update on this fiber. - if (fiber.tag === ClassComponent) { - // Schedule a force update on the work-in-progress. - var lane = pickArbitraryLane(renderLanes); - var update = createUpdate(lane); - update.tag = ForceUpdate; // TODO: Because we don't have a work-in-progress, this will add the - // update to the current fiber, too, which means it will persist even if - // this render is thrown away. Since it's a race condition, not sure it's - // worth fixing. - // Inlined `enqueueUpdate` to remove interleaved update check + workInProgress.flags |= Update; + bubbleProperties(workInProgress); - var updateQueue = fiber.updateQueue; + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + var _isTimedOutSuspense = nextState !== null; - if (updateQueue === null); - else { - var sharedQueue = updateQueue.shared; - var pending = sharedQueue.pending; + if (_isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var _primaryChildFragment = workInProgress.child; - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; + if (_primaryChildFragment !== null) { + // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + _primaryChildFragment.treeBaseDuration; + } } - - sharedQueue.pending = update; } } - fiber.lanes = mergeLanes(fiber.lanes, renderLanes); - var alternate = fiber.alternate; + return false; + } + } else { + // Successfully completed this tree. If this was a forced client render, + // there may have been recoverable errors during first hydration + // attempt. If so, add them to a queue so we can log them in the + // commit phase. + upgradeHydrationErrorsToRecoverable(); // Fall through to normal Suspense path - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, renderLanes); - } + return true; + } + } - scheduleContextWorkOnParentPath( - fiber.return, - renderLanes, - workInProgress - ); // Mark the updated lanes on the list, too. + function completeWork(current, workInProgress, renderLanes) { + var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing - list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the - // dependency list. + switch (workInProgress.tag) { + case IndeterminateComponent: + case LazyComponent: + case SimpleMemoComponent: + case FunctionComponent: + case ForwardRef: + case Fragment: + case Mode: + case Profiler: + case ContextConsumer: + case MemoComponent: + bubbleProperties(workInProgress); + return null; - break; + case ClassComponent: { + bubbleProperties(workInProgress); + return null; } - dependency = dependency.next; - } - } else if (fiber.tag === ContextProvider) { - // Don't scan deeper if this is a matching provider - nextFiber = fiber.type === workInProgress.type ? null : fiber.child; - } else if (fiber.tag === DehydratedFragment) { - // If a dehydrated suspense boundary is in this subtree, we don't know - // if it will have any context consumers in it. The best we can do is - // mark it as having updates. - var parentSuspense = fiber.return; + case HostRoot: { + var fiberRoot = workInProgress.stateNode; - if (parentSuspense === null) { - throw new Error( - "We just came from a parent so we must have had a parent. This is a bug in React." - ); - } + if (enableTransitionTracing) { + var transitions = getWorkInProgressTransitions(); // We set the Passive flag here because if there are new transitions, + // we will need to schedule callbacks and process the transitions, + // which we do in the passive phase - parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); - var _alternate = parentSuspense.alternate; + if (transitions !== null) { + workInProgress.flags |= Passive$1; + } + } - if (_alternate !== null) { - _alternate.lanes = mergeLanes(_alternate.lanes, renderLanes); - } // This is intentionally passing this fiber as the parent - // because we want to schedule this fiber as having work - // on its children. We'll use the childLanes on - // this fiber to indicate that a context has changed. + { + var previousCache = null; - scheduleContextWorkOnParentPath( - parentSuspense, - renderLanes, - workInProgress - ); - nextFiber = fiber.sibling; - } else { - // Traverse down. - nextFiber = fiber.child; - } + if (current !== null) { + previousCache = current.memoizedState.cache; + } - if (nextFiber !== null) { - // Set the return pointer of the child to the work-in-progress fiber. - nextFiber.return = fiber; - } else { - // No child. Traverse to next sibling. - nextFiber = fiber; + var cache = workInProgress.memoizedState.cache; - while (nextFiber !== null) { - if (nextFiber === workInProgress) { - // We're back to the root of this subtree. Exit. - nextFiber = null; - break; - } + if (cache !== previousCache) { + // Run passive effects to retain/release the cache. + workInProgress.flags |= Passive$1; + } - var sibling = nextFiber.sibling; + popCacheProvider(workInProgress); + } - if (sibling !== null) { - // Set the return pointer of the sibling to the work-in-progress fiber. - sibling.return = nextFiber.return; - nextFiber = sibling; - break; - } // No more siblings. Traverse up. + if (enableTransitionTracing) { + popRootMarkerInstance(workInProgress); + } - nextFiber = nextFiber.return; - } - } + popRootTransition(workInProgress); + popHostContainer(workInProgress); - fiber = nextFiber; - } -} + if (fiberRoot.pendingContext) { + fiberRoot.context = fiberRoot.pendingContext; + fiberRoot.pendingContext = null; + } -function propagateContextChanges( - workInProgress, - contexts, - renderLanes, - forcePropagateEntireTree -) { - // Only used by lazy implementation - if (!enableLazyContextPropagation) { - return; - } - - var fiber = workInProgress.child; - - if (fiber !== null) { - // Set the return pointer of the child to the work-in-progress fiber. - fiber.return = workInProgress; - } - - while (fiber !== null) { - var nextFiber = void 0; // Visit this fiber. - - var list = fiber.dependencies; - - if (list !== null) { - nextFiber = fiber.child; - var dep = list.firstContext; - - findChangedDep: while (dep !== null) { - // Assigning these to constants to help Flow - var dependency = dep; - var consumer = fiber; - - for (var i = 0; i < contexts.length; i++) { - var context = contexts[i]; // Check if the context matches. - // TODO: Compare selected values to bail out early. - - if (dependency.context === context) { - // Match! Schedule an update on this fiber. - // In the lazy implementation, don't mark a dirty flag on the - // dependency itself. Not all changes are propagated, so we can't - // rely on the propagation function alone to determine whether - // something has changed; the consumer will check. In the future, we - // could add back a dirty flag as an optimization to avoid double - // checking, but until we have selectors it's not really worth - // the trouble. - consumer.lanes = mergeLanes(consumer.lanes, renderLanes); - var alternate = consumer.alternate; - - if (alternate !== null) { - alternate.lanes = mergeLanes(alternate.lanes, renderLanes); - } - - scheduleContextWorkOnParentPath( - consumer.return, - renderLanes, - workInProgress - ); + if (current === null || current.child === null) { + // If we hydrated, pop so that we can delete any remaining children + // that weren't hydrated. + var wasHydrated = popHydrationState(); - if (!forcePropagateEntireTree) { - // During lazy propagation, when we find a match, we can defer - // propagating changes to the children, because we're going to - // visit them during render. We should continue propagating the - // siblings, though - nextFiber = null; - } // Since we already found a match, we can stop traversing the - // dependency list. + if (wasHydrated) { + // If we hydrated, then we'll need to schedule an update for + // the commit side-effects on the root. + markUpdate(workInProgress); + } else { + if (current !== null) { + var prevState = current.memoizedState; + + if ( + // Check if this is a client root + !prevState.isDehydrated || // Check if we reverted to client rendering (e.g. due to an error) + (workInProgress.flags & ForceClientRender) !== NoFlags$1 + ) { + // Schedule an effect to clear this container at the start of the + // next commit. This handles the case of React rendering into a + // container with previous children. It's also safe to do for + // updates too, because current.child would only be null if the + // previous render was null (so the container would already + // be empty). + workInProgress.flags |= Snapshot; // If this was a forced client render, there may have been + // recoverable errors during first hydration attempt. If so, add + // them to a queue so we can log them in the commit phase. + + upgradeHydrationErrorsToRecoverable(); + } + } + } + } + bubbleProperties(workInProgress); - break findChangedDep; + if (enableTransitionTracing) { + if ((workInProgress.subtreeFlags & Visibility) !== NoFlags$1) { + // If any of our suspense children toggle visibility, this means that + // the pending boundaries array needs to be updated, which we only + // do in the passive phase. + workInProgress.flags |= Passive$1; + } } + + return null; } - dep = dependency.next; - } - } else if (fiber.tag === DehydratedFragment) { - // If a dehydrated suspense boundary is in this subtree, we don't know - // if it will have any context consumers in it. The best we can do is - // mark it as having updates. - var parentSuspense = fiber.return; + case HostHoistable: - if (parentSuspense === null) { - throw new Error( - "We just came from a parent so we must have had a parent. This is a bug in React." - ); - } + case HostSingleton: - parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); - var _alternate2 = parentSuspense.alternate; + case HostComponent: { + popHostContext(workInProgress); + var _type2 = workInProgress.type; - if (_alternate2 !== null) { - _alternate2.lanes = mergeLanes(_alternate2.lanes, renderLanes); - } // This is intentionally passing this fiber as the parent - // because we want to schedule this fiber as having work - // on its children. We'll use the childLanes on - // this fiber to indicate that a context has changed. + if (current !== null && workInProgress.stateNode != null) { + updateHostComponent(current, workInProgress, _type2, newProps); - scheduleContextWorkOnParentPath( - parentSuspense, - renderLanes, - workInProgress - ); - nextFiber = null; - } else { - // Traverse down. - nextFiber = fiber.child; - } + if (current.ref !== workInProgress.ref) { + markRef(workInProgress); + } + } else { + if (!newProps) { + if (workInProgress.stateNode === null) { + 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." + ); + } // This can happen when we abort work. - if (nextFiber !== null) { - // Set the return pointer of the child to the work-in-progress fiber. - nextFiber.return = fiber; - } else { - // No child. Traverse to next sibling. - nextFiber = fiber; + bubbleProperties(workInProgress); + return null; + } - while (nextFiber !== null) { - if (nextFiber === workInProgress) { - // We're back to the root of this subtree. Exit. - nextFiber = null; - break; - } + getHostContext(); // TODO: Move createInstance to beginWork and keep it on a context + // "stack" as the parent. Then append children as we go in beginWork + // or completeWork depending on whether we want to add them top->down or + // bottom->up. Top->down is faster in IE11. - var sibling = nextFiber.sibling; + var _wasHydrated2 = popHydrationState(); - if (sibling !== null) { - // Set the return pointer of the sibling to the work-in-progress fiber. - sibling.return = nextFiber.return; - nextFiber = sibling; - break; - } // No more siblings. Traverse up. + if (_wasHydrated2) { + // TODO: Move this and createInstance step into the beginPhase + // to consolidate. + prepareToHydrateHostInstance(); + } else { + getRootHostContainer(); - nextFiber = nextFiber.return; - } - } + var _instance3 = createInstance(_type2, newProps); // TODO: For persistent renderers, we should pass children as part + // of the initial instance creation - fiber = nextFiber; - } -} + appendAllChildren(_instance3, workInProgress); + workInProgress.stateNode = _instance3; // Certain renderers require commit-time effects for initial mount. + } -function lazilyPropagateParentContextChanges( - current, - workInProgress, - renderLanes -) { - var forcePropagateEntireTree = false; - propagateParentContextChanges( - current, - workInProgress, - renderLanes, - forcePropagateEntireTree - ); -} // Used for propagating a deferred tree (Suspense, Offscreen). We must propagate -// to the entire subtree, because we won't revisit it until after the current -// render has completed, at which point we'll have lost track of which providers -// have changed. - -function propagateParentContextChangesToDeferredTree( - current, - workInProgress, - renderLanes -) { - var forcePropagateEntireTree = true; - propagateParentContextChanges( - current, - workInProgress, - renderLanes, - forcePropagateEntireTree - ); -} + if (workInProgress.ref !== null) { + // If there is a ref on a host node we need to schedule a callback + markRef(workInProgress); + } + } -function propagateParentContextChanges( - current, - workInProgress, - renderLanes, - forcePropagateEntireTree -) { - if (!enableLazyContextPropagation) { - return; - } // Collect all the parent providers that changed. Since this is usually small - // number, we use an Array instead of Set. + bubbleProperties(workInProgress); // This must come at the very end of the complete phase, because it might + // throw to suspend, and if the resource immediately loads, the work loop + // will resume rendering as if the work-in-progress completed. So it must + // fully complete. - var contexts = null; - var parent = workInProgress; - var isInsidePropagationBailout = false; + preloadInstanceAndSuspendIfNeeded(workInProgress); + return null; + } - while (parent !== null) { - if (!isInsidePropagationBailout) { - if ((parent.flags & NeedsPropagation) !== NoFlags$1) { - isInsidePropagationBailout = true; - } else if ((parent.flags & DidPropagateContext) !== NoFlags$1) { - break; - } - } + case HostText: { + var newText = newProps; - if (parent.tag === ContextProvider) { - var currentParent = parent.alternate; + if (current && workInProgress.stateNode != null) { + var oldText = current.memoizedProps; // If we have an alternate, that means this is an update and we need + // to schedule a side-effect to do the updates. - if (currentParent === null) { - throw new Error("Should have a current fiber. This is a bug in React."); - } + updateHostText(current, workInProgress, oldText, newText); + } else { + if (typeof newText !== "string") { + if (workInProgress.stateNode === null) { + 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." + ); + } // This can happen when we abort work. + } - var oldProps = currentParent.memoizedProps; + getRootHostContainer(); - if (oldProps !== null) { - var providerType = parent.type; - var context = providerType._context; - var newProps = parent.pendingProps; - var newValue = newProps.value; - var oldValue = oldProps.value; + getHostContext(); - if (!objectIs(newValue, oldValue)) { - if (contexts !== null) { - contexts.push(context); - } else { - contexts = [context]; + var _wasHydrated3 = popHydrationState(); + + if (_wasHydrated3) { + if (prepareToHydrateHostTextInstance()) { + markUpdate(workInProgress); + } + } else { + workInProgress.stateNode = createTextInstance(newText); + } } + + bubbleProperties(workInProgress); + return null; } - } - } - parent = parent.return; - } + case SuspenseComponent: { + popSuspenseHandler(workInProgress); + var nextState = workInProgress.memoizedState; // Special path for dehydrated boundaries. We may eventually move this + // to its own fiber type so that we can add other kinds of hydration + // boundaries that aren't associated with a Suspense tree. In anticipation + // of such a refactor, all the hydration logic is contained in + // this branch. - if (contexts !== null) { - // If there were any changed providers, search through the children and - // propagate their changes. - propagateContextChanges( - workInProgress, - contexts, - renderLanes, - forcePropagateEntireTree - ); - } // This is an optimization so that we only propagate once per subtree. If a - // deeply nested child bails out, and it calls this propagation function, it - // uses this flag to know that the remaining ancestor providers have already - // been propagated. - // - // NOTE: This optimization is only necessary because we sometimes enter the - // begin phase of nodes that don't have any work scheduled on them — - // specifically, the siblings of a node that _does_ have scheduled work. The - // siblings will bail out and call this function again, even though we already - // propagated content changes to it and its subtree. So we use this flag to - // mark that the parent providers already propagated. - // - // Unfortunately, though, we need to ignore this flag when we're inside a - // tree whose context propagation was deferred — that's what the - // `NeedsPropagation` flag is for. - // - // If we could instead bail out before entering the siblings' begin phase, - // then we could remove both `DidPropagateContext` and `NeedsPropagation`. - // Consider this as part of the next refactor to the fiber tree structure. - - workInProgress.flags |= DidPropagateContext; -} + if ( + current === null || + (current.memoizedState !== null && + current.memoizedState.dehydrated !== null) + ) { + var fallthroughToNormalSuspensePath = + completeDehydratedSuspenseBoundary( + current, + workInProgress, + nextState + ); -function checkIfContextChanged(currentDependencies) { - if (!enableLazyContextPropagation) { - return false; - } // Iterate over the current dependencies to see if something changed. This - // only gets called if props and state has already bailed out, so it's a - // relatively uncommon path, except at the root of a changed subtree. - // Alternatively, we could move these comparisons into `readContext`, but - // that's a much hotter path, so I think this is an appropriate trade off. + if (!fallthroughToNormalSuspensePath) { + if (workInProgress.flags & ForceClientRender) { + // Special case. There were remaining unhydrated nodes. We treat + // this as a mismatch. Revert to client rendering. + return workInProgress; + } else { + // Did not finish hydrating, either because this is the initial + // render or because something suspended. + return null; + } + } // Continue with the normal Suspense path. + } - var dependency = currentDependencies.firstContext; + if ((workInProgress.flags & DidCapture) !== NoFlags$1) { + // Something suspended. Re-render with the fallback children. + workInProgress.lanes = renderLanes; // Do not reset the effect list. - while (dependency !== null) { - var context = dependency.context; - var newValue = context._currentValue2; - var oldValue = dependency.memoizedValue; + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } // Don't bubble properties in this case. - if (!objectIs(newValue, oldValue)) { - return true; - } + return workInProgress; + } - dependency = dependency.next; - } + var nextDidTimeout = nextState !== null; + var prevDidTimeout = + current !== null && current.memoizedState !== null; - return false; -} -function prepareToReadContext(workInProgress, renderLanes) { - currentlyRenderingFiber = workInProgress; - lastContextDependency = null; - lastFullyObservedContext = null; - var dependencies = workInProgress.dependencies; - - if (dependencies !== null) { - if (enableLazyContextPropagation) { - // Reset the work-in-progress list - dependencies.firstContext = null; - } else { - var firstContext = dependencies.firstContext; + if (nextDidTimeout) { + var offscreenFiber = workInProgress.child; + var _previousCache = null; - if (firstContext !== null) { - if (includesSomeLane(dependencies.lanes, renderLanes)) { - // Context list has a pending update. Mark that this fiber performed work. - markWorkInProgressReceivedUpdate(); - } // Reset the work-in-progress list + if ( + offscreenFiber.alternate !== null && + offscreenFiber.alternate.memoizedState !== null && + offscreenFiber.alternate.memoizedState.cachePool !== null + ) { + _previousCache = + offscreenFiber.alternate.memoizedState.cachePool.pool; + } - dependencies.firstContext = null; - } - } - } -} -function readContext(context) { - { - // This warning would fire if you read context inside a Hook like useMemo. - // Unlike the class check below, it's not enforced in production for perf. - if (isDisallowedContextReadInDEV) { - 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()." - ); - } - } + var _cache = null; - return readContextForConsumer(currentlyRenderingFiber, context); -} -function readContextDuringReconcilation(consumer, context, renderLanes) { - if (currentlyRenderingFiber === null) { - prepareToReadContext(consumer, renderLanes); - } + if ( + offscreenFiber.memoizedState !== null && + offscreenFiber.memoizedState.cachePool !== null + ) { + _cache = offscreenFiber.memoizedState.cachePool.pool; + } - return readContextForConsumer(consumer, context); -} + if (_cache !== _previousCache) { + // Run passive effects to retain/release the cache. + offscreenFiber.flags |= Passive$1; + } + } // If the suspended state of the boundary changes, we need to schedule + // a passive effect, which is when we process the transitions + + if (nextDidTimeout !== prevDidTimeout) { + if (enableTransitionTracing) { + var _offscreenFiber = workInProgress.child; + _offscreenFiber.flags |= Passive$1; + } // If the suspended state of the boundary changes, we need to schedule + // an effect to toggle the subtree's visibility. When we switch from + // fallback -> primary, the inner Offscreen fiber schedules this effect + // as part of its normal complete phase. But when we switch from + // primary -> fallback, the inner Offscreen fiber does not have a complete + // phase. So we need to schedule its effect here. + // + // We also use this flag to connect/disconnect the effects, but the same + // logic applies: when re-connecting, the Offscreen fiber's complete + // phase will handle scheduling the effect. It's only when the fallback + // is active that we have to do anything special. + + if (nextDidTimeout) { + var _offscreenFiber2 = workInProgress.child; + _offscreenFiber2.flags |= Visibility; + } + } -function readContextForConsumer(consumer, context) { - var value = context._currentValue2; + var retryQueue = workInProgress.updateQueue; + scheduleRetryEffect(workInProgress, retryQueue); - if (lastFullyObservedContext === context); - else { - var contextItem = { - context: context, - memoizedValue: value, - next: null - }; + if ( + workInProgress.updateQueue !== null && + workInProgress.memoizedProps.suspenseCallback != null + ) { + // Always notify the callback + // TODO: Move to passive phase + workInProgress.flags |= Update; + } - if (lastContextDependency === null) { - if (consumer === null) { - 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()." - ); - } // This is the first dependency for this component. Create a new list. + bubbleProperties(workInProgress); - lastContextDependency = contextItem; - consumer.dependencies = { - lanes: NoLanes, - firstContext: contextItem - }; + { + if ((workInProgress.mode & ProfileMode) !== NoMode) { + if (nextDidTimeout) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var primaryChildFragment = workInProgress.child; + + if (primaryChildFragment !== null) { + // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator + workInProgress.treeBaseDuration -= + primaryChildFragment.treeBaseDuration; + } + } + } + } - if (enableLazyContextPropagation) { - consumer.flags |= NeedsPropagation; - } - } else { - // Append a new context item. - lastContextDependency = lastContextDependency.next = contextItem; - } - } + return null; + } - return value; -} + case HostPortal: + popHostContainer(workInProgress); + + bubbleProperties(workInProgress); + return null; + + case ContextProvider: + // Pop provider fiber + var context = workInProgress.type._context; + popProvider(context, workInProgress); + bubbleProperties(workInProgress); + return null; -// replace it with a lightweight shim that only has the features we use. + case IncompleteClassComponent: { + bubbleProperties(workInProgress); + return null; + } + + case SuspenseListComponent: { + popSuspenseListContext(workInProgress); + var renderState = workInProgress.memoizedState; -var AbortControllerLocal = - typeof AbortController !== "undefined" - ? AbortController // $FlowFixMe[missing-this-annot] - : // $FlowFixMe[prop-missing] - function AbortControllerShim() { - var listeners = []; - var signal = (this.signal = { - aborted: false, - addEventListener: function (type, listener) { - listeners.push(listener); + if (renderState === null) { + // We're running in the default, "independent" mode. + // We don't do anything in this mode. + bubbleProperties(workInProgress); + return null; } - }); - this.abort = function () { - signal.aborted = true; - listeners.forEach(function (listener) { - return listener(); - }); - }; - }; // Intentionally not named imports because Rollup would -// use dynamic dispatch for CommonJS interop named imports. - -var scheduleCallback$1 = Scheduler.unstable_scheduleCallback, - NormalPriority = Scheduler.unstable_NormalPriority; -var CacheContext = { - $$typeof: REACT_CONTEXT_TYPE, - // We don't use Consumer/Provider for Cache components. So we'll cheat. - Consumer: null, - Provider: null, - // We'll initialize these at the root. - _currentValue: null, - _currentValue2: null, - _threadCount: 0, - _defaultValue: null, - _globalName: null -}; - -{ - CacheContext._currentRenderer = null; - CacheContext._currentRenderer2 = null; -} // Creates a new empty Cache instance with a ref-count of 0. The caller is responsible -// for retaining the cache once it is in use (retainCache), and releasing the cache -// once it is no longer needed (releaseCache). - -function createCache() { - var cache = { - controller: new AbortControllerLocal(), - data: new Map(), - refCount: 0 - }; - return cache; -} -function retainCache(cache) { - { - if (cache.controller.signal.aborted) { - warn( - "A cache instance was retained after it was already freed. " + - "This likely indicates a bug in React." - ); - } - } + var didSuspendAlready = + (workInProgress.flags & DidCapture) !== NoFlags$1; + var renderedTail = renderState.rendering; + + if (renderedTail === null) { + // We just rendered the head. + if (!didSuspendAlready) { + // This is the first pass. We need to figure out if anything is still + // suspended in the rendered set. + // If new content unsuspended, but there's still some content that + // didn't. Then we need to do a second pass that forces everything + // to keep showing their fallbacks. + // We might be suspended if something in this render pass suspended, or + // something in the previous committed pass suspended. Otherwise, + // there's no chance so we can skip the expensive call to + // findFirstSuspended. + var cannotBeSuspended = + renderHasNotSuspendedYet() && + (current === null || + (current.flags & DidCapture) === NoFlags$1); + + if (!cannotBeSuspended) { + var row = workInProgress.child; + + while (row !== null) { + var suspended = findFirstSuspended(row); + + if (suspended !== null) { + didSuspendAlready = true; + workInProgress.flags |= DidCapture; + cutOffTailIfNeeded(renderState, false); // If this is a newly suspended tree, it might not get committed as + // part of the second pass. In that case nothing will subscribe to + // its thenables. Instead, we'll transfer its thenables to the + // SuspenseList so that it can retry if they resolve. + // There might be multiple of these in the list but since we're + // going to wait for all of them anyway, it doesn't really matter + // which ones gets to ping. In theory we could get clever and keep + // track of how many dependencies remain but it gets tricky because + // in the meantime, we can add/remove/change items and dependencies. + // We might bail out of the loop before finding any but that + // doesn't matter since that means that the other boundaries that + // we did find already has their listeners attached. + + var _retryQueue = suspended.updateQueue; + workInProgress.updateQueue = _retryQueue; + scheduleRetryEffect(workInProgress, _retryQueue); // Rerender the whole list, but this time, we'll force fallbacks + // to stay in place. + // Reset the effect flags before doing the second pass since that's now invalid. + // Reset the child fibers to their original state. + + workInProgress.subtreeFlags = NoFlags$1; + resetChildFibers(workInProgress, renderLanes); // Set up the Suspense List Context to force suspense and + // immediately rerender the children. + + pushSuspenseListContext( + workInProgress, + setShallowSuspenseListContext( + suspenseStackCursor.current, + ForceSuspenseFallback + ) + ); // Don't bubble properties in this case. + + return workInProgress.child; + } - cache.refCount++; -} // Cleanup a cache instance, potentially freeing it if there are no more references + row = row.sibling; + } + } -function releaseCache(cache) { - cache.refCount--; + if ( + renderState.tail !== null && + now$1() > getRenderTargetTime() + ) { + // We have already passed our CPU deadline but we still have rows + // left in the tail. We'll just give up further attempts to render + // the main content and only render fallbacks. + workInProgress.flags |= DidCapture; + didSuspendAlready = true; + cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. + + workInProgress.lanes = SomeRetryLane; + } + } else { + cutOffTailIfNeeded(renderState, false); + } // Next we're going to render the tail. + } else { + // Append the rendered row to the child list. + if (!didSuspendAlready) { + var _suspended = findFirstSuspended(renderedTail); - { - if (cache.refCount < 0) { - warn( - "A cache instance was released after it was already freed. " + - "This likely indicates a bug in React." - ); - } - } + if (_suspended !== null) { + workInProgress.flags |= DidCapture; + didSuspendAlready = true; // Ensure we transfer the update queue to the parent so that it doesn't + // get lost if this row ends up dropped during a second pass. + + var _retryQueue2 = _suspended.updateQueue; + workInProgress.updateQueue = _retryQueue2; + scheduleRetryEffect(workInProgress, _retryQueue2); + cutOffTailIfNeeded(renderState, true); // This might have been modified. + + if ( + renderState.tail === null && + renderState.tailMode === "hidden" && + !renderedTail.alternate && + !getIsHydrating() // We don't cut it if we're hydrating. + ) { + // We're done. + bubbleProperties(workInProgress); + return null; + } + } else if ( + // The time it took to render last row is greater than the remaining + // time we have to render. So rendering one more row would likely + // exceed it. + now$1() * 2 - renderState.renderingStartTime > + getRenderTargetTime() && + renderLanes !== OffscreenLane + ) { + // We have now passed our CPU deadline and we'll just give up further + // attempts to render the main content and only render fallbacks. + // The assumption is that this is usually faster. + workInProgress.flags |= DidCapture; + didSuspendAlready = true; + cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. + + workInProgress.lanes = SomeRetryLane; + } + } - if (cache.refCount === 0) { - scheduleCallback$1(NormalPriority, function () { - cache.controller.abort(); - }); - } -} -function pushCacheProvider(workInProgress, cache) { - pushProvider(workInProgress, CacheContext, cache); -} -function popCacheProvider(workInProgress, cache) { - popProvider(CacheContext, workInProgress); -} + if (renderState.isBackwards) { + // The effect list of the backwards tail will have been added + // to the end. This breaks the guarantee that life-cycles fire in + // sibling order but that isn't a strong guarantee promised by React. + // Especially since these might also just pop in during future commits. + // Append to the beginning of the list. + renderedTail.sibling = workInProgress.child; + workInProgress.child = renderedTail; + } else { + var previousSibling = renderState.last; -var ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig; -var NoTransition = null; -function requestCurrentTransition() { - return ReactCurrentBatchConfig$1.transition; -} // When retrying a Suspense/Offscreen boundary, we restore the cache that was -// used during the previous render by placing it here, on the stack. + if (previousSibling !== null) { + previousSibling.sibling = renderedTail; + } else { + workInProgress.child = renderedTail; + } -var resumedCache = createCursor(null); // During the render/synchronous commit phase, we don't actually process the -// transitions. Therefore, we want to lazily combine transitions. Instead of -// comparing the arrays of transitions when we combine them and storing them -// and filtering out the duplicates, we will instead store the unprocessed transitions -// in an array and actually filter them in the passive phase. + renderState.last = renderedTail; + } + } -var transitionStack = createCursor(null); + if (renderState.tail !== null) { + // We still have tail rows to render. + // Pop a row. + var next = renderState.tail; + renderState.rendering = next; + renderState.tail = next.sibling; + renderState.renderingStartTime = now$1(); + next.sibling = null; // Restore the context. + // TODO: We can probably just avoid popping it instead and only + // setting it the first time we go from not suspended to suspended. + + var suspenseContext = suspenseStackCursor.current; + + if (didSuspendAlready) { + suspenseContext = setShallowSuspenseListContext( + suspenseContext, + ForceSuspenseFallback + ); + } else { + suspenseContext = + setDefaultShallowSuspenseListContext(suspenseContext); + } -function peekCacheFromPool() { - // If we're rendering inside a Suspense boundary that is currently hidden, - // we should use the same cache that we used during the previous render, if - // one exists. + pushSuspenseListContext(workInProgress, suspenseContext); // Do a pass over the next row. + // Don't bubble properties in this case. - var cacheResumedFromPreviousRender = resumedCache.current; + return next; + } - if (cacheResumedFromPreviousRender !== null) { - return cacheResumedFromPreviousRender; - } // Otherwise, check the root's cache pool. + bubbleProperties(workInProgress); + return null; + } - var root = getWorkInProgressRoot(); - var cacheFromRootCachePool = root.pooledCache; - return cacheFromRootCachePool; -} + case ScopeComponent: { + { + if (current === null) { + var scopeInstance = createScopeInstance(); + workInProgress.stateNode = scopeInstance; + prepareScopeUpdate(); + + if (workInProgress.ref !== null) { + markRef(workInProgress); + markUpdate(workInProgress); + } + } else { + if (workInProgress.ref !== null) { + markUpdate(workInProgress); + } -function requestCacheFromPool(renderLanes) { - // Similar to previous function, except if there's not already a cache in the - // pool, we allocate a new one. - var cacheFromPool = peekCacheFromPool(); - - if (cacheFromPool !== null) { - return cacheFromPool; - } // Create a fresh cache and add it to the root cache pool. A cache can have - // multiple owners: - // - A cache pool that lives on the FiberRoot. This is where all fresh caches - // are originally created (TODO: except during refreshes, until we implement - // this correctly). The root takes ownership immediately when the cache is - // created. Conceptually, root.pooledCache is an Option> (owned), - // and the return value of this function is a &Arc (borrowed). - // - One of several fiber types: host root, cache boundary, suspense - // component. These retain and release in the commit phase. - - var root = getWorkInProgressRoot(); - var freshCache = createCache(); - root.pooledCache = freshCache; - retainCache(freshCache); - - if (freshCache !== null) { - root.pooledCacheLanes |= renderLanes; - } - - return freshCache; -} -function pushRootTransition(workInProgress, root, renderLanes) { - if (enableTransitionTracing) { - var rootTransitions = getWorkInProgressTransitions(); - push(transitionStack, rootTransitions, workInProgress); - } -} -function popRootTransition(workInProgress, root, renderLanes) { - if (enableTransitionTracing) { - pop(transitionStack, workInProgress); - } -} -function pushTransition( - offscreenWorkInProgress, - prevCachePool, - newTransitions -) { - { - if (prevCachePool === null) { - push(resumedCache, resumedCache.current, offscreenWorkInProgress); - } else { - push(resumedCache, prevCachePool.pool, offscreenWorkInProgress); - } - } + if (current.ref !== workInProgress.ref) { + markRef(workInProgress); + } + } - if (enableTransitionTracing) { - if (transitionStack.current === null) { - push(transitionStack, newTransitions, offscreenWorkInProgress); - } else if (newTransitions === null) { - push(transitionStack, transitionStack.current, offscreenWorkInProgress); - } else { - push( - transitionStack, - transitionStack.current.concat(newTransitions), - offscreenWorkInProgress - ); - } - } -} -function popTransition(workInProgress, current) { - if (current !== null) { - if (enableTransitionTracing) { - pop(transitionStack, workInProgress); - } + bubbleProperties(workInProgress); + return null; + } + } - { - pop(resumedCache, workInProgress); - } - } -} -function getPendingTransitions() { - if (!enableTransitionTracing) { - return null; - } + case OffscreenComponent: + case LegacyHiddenComponent: { + popSuspenseHandler(workInProgress); + popHiddenContext(workInProgress); + var _nextState = workInProgress.memoizedState; + var nextIsHidden = _nextState !== null; // Schedule a Visibility effect if the visibility has changed - return transitionStack.current; -} -function getSuspendedCache() { - // cache that would have been used to render fresh data during this render, - // if there was any, so that we can resume rendering with the same cache when - // we receive more data. - - var cacheFromPool = peekCacheFromPool(); - - if (cacheFromPool === null) { - return null; - } - - return { - // We must also save the parent, so that when we resume we can detect - // a refresh. - parent: CacheContext._currentValue2, - pool: cacheFromPool - }; -} -function getOffscreenDeferredCache() { - var cacheFromPool = peekCacheFromPool(); - - if (cacheFromPool === null) { - return null; - } - - return { - // We must also store the parent, so that when we resume we can detect - // a refresh. - parent: CacheContext._currentValue2, - pool: cacheFromPool - }; -} + if (workInProgress.tag === LegacyHiddenComponent); + else { + if (current !== null) { + var _prevState = current.memoizedState; + var prevIsHidden = _prevState !== null; -function getSuspenseFallbackChild(fiber) { - return fiber.child.sibling.child; -} + if (prevIsHidden !== nextIsHidden) { + workInProgress.flags |= Visibility; + } + } else { + // On initial mount, we only need a Visibility effect if the tree + // is hidden. + if (nextIsHidden) { + workInProgress.flags |= Visibility; + } + } + } -var emptyObject = {}; + if ( + !nextIsHidden || + (workInProgress.mode & ConcurrentMode) === NoMode + ) { + bubbleProperties(workInProgress); + } else { + // Don't bubble properties for hidden children unless we're rendering + // at offscreen priority. + if ( + includesSomeLane(renderLanes, OffscreenLane) && // Also don't bubble if the tree suspended + (workInProgress.flags & DidCapture) === NoLanes + ) { + bubbleProperties(workInProgress); // Check if there was an insertion or update in the hidden subtree. + // If so, we need to hide those nodes in the commit phase, so + // schedule a visibility effect. -function collectScopedNodes(node, fn, scopedNodes) { - { - if (node.tag === HostComponent) { - var type = node.type, - memoizedProps = node.memoizedProps, - stateNode = node.stateNode; - var instance = getPublicInstance(stateNode); + if ( + workInProgress.tag !== LegacyHiddenComponent && + workInProgress.subtreeFlags & (Placement | Update) + ) { + workInProgress.flags |= Visibility; + } + } + } - if ( - instance !== null && - fn(type, memoizedProps || emptyObject, instance) === true - ) { - scopedNodes.push(instance); - } - } + var offscreenQueue = workInProgress.updateQueue; - var child = node.child; + if (offscreenQueue !== null) { + var _retryQueue3 = offscreenQueue.retryQueue; + scheduleRetryEffect(workInProgress, _retryQueue3); + } - if (isFiberSuspenseAndTimedOut(node)) { - child = getSuspenseFallbackChild(node); - } + { + var _previousCache2 = null; - if (child !== null) { - collectScopedNodesFromChildren(child, fn, scopedNodes); - } - } -} + if ( + current !== null && + current.memoizedState !== null && + current.memoizedState.cachePool !== null + ) { + _previousCache2 = current.memoizedState.cachePool.pool; + } -function collectFirstScopedNode(node, fn) { - { - if (node.tag === HostComponent) { - var type = node.type, - memoizedProps = node.memoizedProps, - stateNode = node.stateNode; - var instance = getPublicInstance(stateNode); + var _cache2 = null; - if (instance !== null && fn(type, memoizedProps, instance) === true) { - return instance; - } - } + if ( + workInProgress.memoizedState !== null && + workInProgress.memoizedState.cachePool !== null + ) { + _cache2 = workInProgress.memoizedState.cachePool.pool; + } - var child = node.child; + if (_cache2 !== _previousCache2) { + // Run passive effects to retain/release the cache. + workInProgress.flags |= Passive$1; + } + } - if (isFiberSuspenseAndTimedOut(node)) { - child = getSuspenseFallbackChild(node); - } + popTransition(workInProgress, current); + return null; + } - if (child !== null) { - return collectFirstScopedNodeFromChildren(child, fn); - } - } + case CacheComponent: { + { + var _previousCache3 = null; - return null; -} + if (current !== null) { + _previousCache3 = current.memoizedState.cache; + } -function collectScopedNodesFromChildren(startingChild, fn, scopedNodes) { - var child = startingChild; + var _cache3 = workInProgress.memoizedState.cache; - while (child !== null) { - collectScopedNodes(child, fn, scopedNodes); - child = child.sibling; - } -} + if (_cache3 !== _previousCache3) { + // Run passive effects to retain/release the cache. + workInProgress.flags |= Passive$1; + } -function collectFirstScopedNodeFromChildren(startingChild, fn) { - var child = startingChild; + popCacheProvider(workInProgress); + bubbleProperties(workInProgress); + } - while (child !== null) { - var scopedNode = collectFirstScopedNode(child, fn); + return null; + } - if (scopedNode !== null) { - return scopedNode; - } + case TracingMarkerComponent: { + if (enableTransitionTracing) { + var _instance4 = workInProgress.stateNode; - child = child.sibling; - } + if (_instance4 !== null) { + popMarkerInstance(workInProgress); + } - return null; -} + bubbleProperties(workInProgress); + } -function collectNearestContextValues(node, context, childContextValues) { - if (node.tag === ContextProvider && node.type._context === context) { - var contextValue = node.memoizedProps.value; - childContextValues.push(contextValue); - } else { - var child = node.child; + return null; + } + } - if (isFiberSuspenseAndTimedOut(node)) { - child = getSuspenseFallbackChild(node); + throw new Error( + "Unknown unit of work tag (" + + workInProgress.tag + + "). This error is likely caused by a bug in " + + "React. Please file an issue." + ); } - if (child !== null) { - collectNearestChildContextValues(child, context, childContextValues); - } - } -} + function unwindWork(current, workInProgress, renderLanes) { + switch (workInProgress.tag) { + case ClassComponent: { + var flags = workInProgress.flags; -function collectNearestChildContextValues( - startingChild, - context, - childContextValues -) { - var child = startingChild; - - while (child !== null) { - collectNearestContextValues(child, context, childContextValues); - child = child.sibling; - } -} + if (flags & ShouldCapture) { + workInProgress.flags = (flags & ~ShouldCapture) | DidCapture; -function DO_NOT_USE_queryAllNodes(fn) { - var currentFiber = getInstanceFromScope(); + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } - if (currentFiber === null) { - return null; - } + return workInProgress; + } - var child = currentFiber.child; - var scopedNodes = []; + return null; + } - if (child !== null) { - collectScopedNodesFromChildren(child, fn, scopedNodes); - } + case HostRoot: { + { + popCacheProvider(workInProgress); + } - return scopedNodes.length === 0 ? null : scopedNodes; -} + if (enableTransitionTracing) { + popRootMarkerInstance(workInProgress); + } -function DO_NOT_USE_queryFirstNode(fn) { - var currentFiber = getInstanceFromScope(); + popRootTransition(workInProgress); + popHostContainer(workInProgress); + var _flags = workInProgress.flags; - if (currentFiber === null) { - return null; - } + if ( + (_flags & ShouldCapture) !== NoFlags$1 && + (_flags & DidCapture) === NoFlags$1 + ) { + // There was an error during render that wasn't captured by a suspense + // boundary. Do a second pass on the root to unmount the children. + workInProgress.flags = (_flags & ~ShouldCapture) | DidCapture; + return workInProgress; + } // We unwound to the root without completing it. Exit. - var child = currentFiber.child; + return null; + } - if (child !== null) { - return collectFirstScopedNodeFromChildren(child, fn); - } + case HostHoistable: + case HostSingleton: + case HostComponent: { + // TODO: popHydrationState + popHostContext(workInProgress); + return null; + } - return null; -} + case SuspenseComponent: { + popSuspenseHandler(workInProgress); + var suspenseState = workInProgress.memoizedState; -function containsNode(node) { - var fiber = getInstanceFromNode(); + if (suspenseState !== null && suspenseState.dehydrated !== null) { + if (workInProgress.alternate === null) { + throw new Error( + "Threw in newly mounted dehydrated component. This is likely a bug in " + + "React. Please file an issue." + ); + } + } - while (fiber !== null) { - if (fiber.tag === ScopeComponent && fiber.stateNode === this) { - return true; - } + var _flags2 = workInProgress.flags; - fiber = fiber.return; - } + if (_flags2 & ShouldCapture) { + workInProgress.flags = (_flags2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. - return false; -} + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } -function getChildContextValues(context) { - var currentFiber = getInstanceFromScope(); + return workInProgress; + } - if (currentFiber === null) { - return []; - } + return null; + } - var child = currentFiber.child; - var childContextValues = []; + case SuspenseListComponent: { + popSuspenseListContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been + // caught by a nested boundary. If not, it should bubble through. - if (child !== null) { - collectNearestChildContextValues(child, context, childContextValues); - } + return null; + } - return childContextValues; -} + case HostPortal: + popHostContainer(workInProgress); + return null; -function createScopeInstance() { - return { - DO_NOT_USE_queryAllNodes: DO_NOT_USE_queryAllNodes, - DO_NOT_USE_queryFirstNode: DO_NOT_USE_queryFirstNode, - containsNode: containsNode, - getChildContextValues: getChildContextValues - }; -} + case ContextProvider: + var context = workInProgress.type._context; + popProvider(context, workInProgress); + return null; -function markUpdate(workInProgress) { - // Tag the fiber with an update effect. This turns a Placement into - // a PlacementAndUpdate. - workInProgress.flags |= Update; -} + case OffscreenComponent: + case LegacyHiddenComponent: { + popSuspenseHandler(workInProgress); + popHiddenContext(workInProgress); + popTransition(workInProgress, current); + var _flags3 = workInProgress.flags; -function markRef(workInProgress) { - workInProgress.flags |= Ref | RefStatic; -} + if (_flags3 & ShouldCapture) { + workInProgress.flags = (_flags3 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. -function appendAllChildren( - parent, - workInProgress, - needsVisibilityToggle, - isHidden -) { - { - // We only have the top Fiber that was created but we need recurse down its - // children to find all the terminal nodes. - var node = workInProgress.child; - - while (node !== null) { - if (node.tag === HostComponent || node.tag === HostText) { - appendInitialChild(parent, node.stateNode); - } else if (node.tag === HostPortal || false); - else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } - - if (node === workInProgress) { - return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } - while (node.sibling === null) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - if (node.return === null || node.return === workInProgress) { - return; + return workInProgress; + } + + return null; } - node = node.return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow + case CacheComponent: + { + popCacheProvider(workInProgress); + } - node.sibling.return = node.return; - node = node.sibling; - } - } -} // An unfortunate fork of appendAllChildren because we have two different parent types. - -function updateHostComponent( - current, - workInProgress, - type, - newProps, - renderLanes -) { - { - // If we have an alternate, that means this is an update and we need to - // schedule a side-effect to do the updates. - var oldProps = current.memoizedProps; - - if (oldProps === newProps) { - // In mutation mode, this is sufficient for a bailout because - // we won't touch this node even if children changed. - return; - } - - markUpdate(workInProgress); - } -} // This function must be called at the very end of the complete phase, because -// it might throw to suspend, and if the resource immediately loads, the work -// loop will resume rendering as if the work-in-progress completed. So it must -// fully complete. -// TODO: This should ideally move to begin phase, but currently the instance is -// not created until the complete phase. For our existing use cases, host nodes -// that suspend don't have children, so it doesn't matter. But that might not -// always be true in the future. - -function preloadInstanceAndSuspendIfNeeded( - workInProgress, - type, - props, - renderLanes -) { - { - // If this flag was set previously, we can remove it. The flag - // represents whether this particular set of props might ever need to - // suspend. The safest thing to do is for maySuspendCommit to always - // return true, but if the renderer is reasonably confident that the - // underlying resource won't be evicted, it can return false as a - // performance optimization. - workInProgress.flags &= ~MaySuspendCommit; - return; - } // Mark this fiber with a flag. This gets set on all host instances -} + return null; -function scheduleRetryEffect(workInProgress, retryQueue) { - var wakeables = retryQueue; - - if (wakeables !== null) { - // Schedule an effect to attach a retry listener to the promise. - // TODO: Move to passive phase - workInProgress.flags |= Update; - } else { - // This boundary suspended, but no wakeables were added to the retry - // queue. Check if the renderer suspended commit. If so, this means - // that once the fallback is committed, we can immediately retry - // rendering again, because rendering wasn't actually blocked. Only - // the commit phase. - // TODO: Consider a model where we always schedule an immediate retry, even - // for normal Suspense. That way the retry can partially render up to the - // first thing that suspends. - if (workInProgress.flags & ScheduleRetry) { - var retryLane = // TODO: This check should probably be moved into claimNextRetryLane - // I also suspect that we need some further consolidation of offscreen - // and retry lanes. - workInProgress.tag !== OffscreenComponent - ? claimNextRetryLane() - : OffscreenLane; - workInProgress.lanes = mergeLanes(workInProgress.lanes, retryLane); - } - } -} + case TracingMarkerComponent: + if (enableTransitionTracing) { + if (workInProgress.stateNode !== null) { + popMarkerInstance(workInProgress); + } + } -function updateHostText(current, workInProgress, oldText, newText) { - { - // If the text differs, mark it as an update. All the work in done in commitWork. - if (oldText !== newText) { - markUpdate(workInProgress); - } - } -} + return null; -function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { - switch (renderState.tailMode) { - case "hidden": { - // Any insertions at the end of the tail list after this point - // should be invisible. If there are already mounted boundaries - // anything before them are not considered for collapsing. - // Therefore we need to go through the whole tail to find if - // there are any. - var tailNode = renderState.tail; - var lastTailNode = null; - - while (tailNode !== null) { - if (tailNode.alternate !== null) { - lastTailNode = tailNode; - } - - tailNode = tailNode.sibling; - } // Next we're simply going to delete all insertions after the - // last rendered item. - - if (lastTailNode === null) { - // All remaining items in the tail are insertions. - renderState.tail = null; - } else { - // Detach the insertion after the last node that was already - // inserted. - lastTailNode.sibling = null; + default: + return null; } - - break; } - case "collapsed": { - // Any insertions at the end of the tail list after this point - // should be invisible. If there are already mounted boundaries - // anything before them are not considered for collapsing. - // Therefore we need to go through the whole tail to find if - // there are any. - var _tailNode = renderState.tail; - var _lastTailNode = null; - - while (_tailNode !== null) { - if (_tailNode.alternate !== null) { - _lastTailNode = _tailNode; + function unwindInterruptedWork(current, interruptedWork, renderLanes) { + switch (interruptedWork.tag) { + case ClassComponent: { + break; } - _tailNode = _tailNode.sibling; - } // Next we're simply going to delete all insertions after the - // last rendered item. + case HostRoot: { + { + popCacheProvider(interruptedWork); + } - if (_lastTailNode === null) { - // All remaining items in the tail are insertions. - if (!hasRenderedATailFallback && renderState.tail !== null) { - // We suspended during the head. We want to show at least one - // row at the tail. So we'll keep on and cut off the rest. - renderState.tail.sibling = null; - } else { - renderState.tail = null; - } - } else { - // Detach the insertion after the last node that was already - // inserted. - _lastTailNode.sibling = null; - } + if (enableTransitionTracing) { + popRootMarkerInstance(interruptedWork); + } - break; - } - } -} + popRootTransition(interruptedWork); + popHostContainer(interruptedWork); + break; + } -function bubbleProperties(completedWork) { - var didBailout = - completedWork.alternate !== null && - completedWork.alternate.child === completedWork.child; - var newChildLanes = NoLanes; - var subtreeFlags = NoFlags$1; - - if (!didBailout) { - // Bubble up the earliest expiration time. - if ((completedWork.mode & ProfileMode) !== NoMode) { - // In profiling mode, resetChildExpirationTime is also used to reset - // profiler durations. - var actualDuration = completedWork.actualDuration; - var treeBaseDuration = completedWork.selfBaseDuration; - var child = completedWork.child; + case HostHoistable: + case HostSingleton: + case HostComponent: { + popHostContext(interruptedWork); + break; + } - while (child !== null) { - newChildLanes = mergeLanes( - newChildLanes, - mergeLanes(child.lanes, child.childLanes) - ); - subtreeFlags |= child.subtreeFlags; - subtreeFlags |= child.flags; // When a fiber is cloned, its actualDuration is reset to 0. This value will - // only be updated if work is done on the fiber (i.e. it doesn't bailout). - // When work is done, it should bubble to the parent's actualDuration. If - // the fiber has not been cloned though, (meaning no work was done), then - // this value will reflect the amount of time spent working on a previous - // render. In that case it should not bubble. We determine whether it was - // cloned by comparing the child pointer. - // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + case HostPortal: + popHostContainer(interruptedWork); + break; - actualDuration += child.actualDuration; // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + case SuspenseComponent: + popSuspenseHandler(interruptedWork); + break; - treeBaseDuration += child.treeBaseDuration; - child = child.sibling; - } + case SuspenseListComponent: + popSuspenseListContext(interruptedWork); + break; - completedWork.actualDuration = actualDuration; - completedWork.treeBaseDuration = treeBaseDuration; - } else { - var _child = completedWork.child; + case ContextProvider: + var context = interruptedWork.type._context; + popProvider(context, interruptedWork); + break; - while (_child !== null) { - newChildLanes = mergeLanes( - newChildLanes, - mergeLanes(_child.lanes, _child.childLanes) - ); - subtreeFlags |= _child.subtreeFlags; - subtreeFlags |= _child.flags; // Update the return pointer so the tree is consistent. This is a code - // smell because it assumes the commit phase is never concurrent with - // the render phase. Will address during refactor to alternate model. + case OffscreenComponent: + case LegacyHiddenComponent: + popSuspenseHandler(interruptedWork); + popHiddenContext(interruptedWork); + popTransition(interruptedWork, current); + break; - _child.return = completedWork; - _child = _child.sibling; - } - } + case CacheComponent: + { + popCacheProvider(interruptedWork); + } - completedWork.subtreeFlags |= subtreeFlags; - } else { - // Bubble up the earliest expiration time. - if ((completedWork.mode & ProfileMode) !== NoMode) { - // In profiling mode, resetChildExpirationTime is also used to reset - // profiler durations. - var _treeBaseDuration = completedWork.selfBaseDuration; - var _child2 = completedWork.child; + break; - while (_child2 !== null) { - newChildLanes = mergeLanes( - newChildLanes, - mergeLanes(_child2.lanes, _child2.childLanes) - ); // "Static" flags share the lifetime of the fiber/hook they belong to, - // so we should bubble those up even during a bailout. All the other - // flags have a lifetime only of a single render + commit, so we should - // ignore them. + case TracingMarkerComponent: + if (enableTransitionTracing) { + var instance = interruptedWork.stateNode; - subtreeFlags |= _child2.subtreeFlags & StaticMask; - subtreeFlags |= _child2.flags & StaticMask; // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + if (instance !== null) { + popMarkerInstance(interruptedWork); + } + } - _treeBaseDuration += _child2.treeBaseDuration; - _child2 = _child2.sibling; + break; } + } - completedWork.treeBaseDuration = _treeBaseDuration; - } else { - var _child3 = completedWork.child; - - while (_child3 !== null) { - newChildLanes = mergeLanes( - newChildLanes, - mergeLanes(_child3.lanes, _child3.childLanes) - ); // "Static" flags share the lifetime of the fiber/hook they belong to, - // so we should bubble those up even during a bailout. All the other - // flags have a lifetime only of a single render + commit, so we should - // ignore them. - - subtreeFlags |= _child3.subtreeFlags & StaticMask; - subtreeFlags |= _child3.flags & StaticMask; // Update the return pointer so the tree is consistent. This is a code - // smell because it assumes the commit phase is never concurrent with - // the render phase. Will address during refactor to alternate model. + // Provided by www + var ReactFbErrorUtils = require("ReactFbErrorUtils"); - _child3.return = completedWork; - _child3 = _child3.sibling; - } + if (typeof ReactFbErrorUtils.invokeGuardedCallback !== "function") { + throw new Error( + "Expected ReactFbErrorUtils.invokeGuardedCallback to be a function." + ); } - completedWork.subtreeFlags |= subtreeFlags; - } - - completedWork.childLanes = newChildLanes; - return didBailout; -} + function invokeGuardedCallbackImpl(name, func, context, a, b, c, d, e, f) { + // This will call `this.onError(err)` if an error was caught. + ReactFbErrorUtils.invokeGuardedCallback.apply(this, arguments); + } -function completeDehydratedSuspenseBoundary( - current, - workInProgress, - nextState -) { - var wasHydrated = popHydrationState(); - - if (nextState !== null && nextState.dehydrated !== null) { - // We might be inside a hydration state the first time we're picking up this - // Suspense boundary, and also after we've reentered it for further hydration. - if (current === null) { - if (!wasHydrated) { + var hasError = false; + var caughtError = null; // Used by event system to capture/rethrow the first error. + var reporter = { + onError: function (error) { + hasError = true; + caughtError = error; + } + }; + /** + * Call a function while guarding against errors that happens within it. + * Returns an error if it throws, otherwise null. + * + * In production, this is implemented using a try-catch. The reason we don't + * use a try-catch directly is so that we can swap out a different + * implementation in DEV mode. + * + * @param {String} name of the guard to use for logging or debugging + * @param {Function} func The function to invoke + * @param {*} context The context to use when calling the function + * @param {...*} args Arguments for function + */ + + function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) { + hasError = false; + caughtError = null; + invokeGuardedCallbackImpl.apply(reporter, arguments); + } + function hasCaughtError() { + return hasError; + } + function clearCaughtError() { + if (hasError) { + var error = caughtError; + hasError = false; + caughtError = null; + return error; + } else { throw new Error( - "A dehydrated suspense component was completed without a hydrated node. " + - "This is probably a bug in React." + "clearCaughtError was called but no error was captured. This error " + + "is likely caused by a bug in React. Please file an issue." ); } + } - prepareToHydrateHostSuspenseInstance(); - bubbleProperties(workInProgress); + var didWarnAboutUndefinedSnapshotBeforeUpdate = null; + + { + didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); + } // Used during the commit phase to track the state of the Offscreen component stack. + // Allows us to avoid traversing the return path to find the nearest Offscreen ancestor. + + var offscreenSubtreeIsHidden = false; + var offscreenSubtreeWasHidden = false; + var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; + var nextEffect = null; // Used for Profiling builds to track updaters. + + var inProgressLanes = null; + var inProgressRoot = null; + + function shouldProfile(current) { + return ( + (current.mode & ProfileMode) !== NoMode && + (getExecutionContext() & CommitContext) !== NoContext + ); + } + function reportUncaughtErrorInDEV(error) { + // Wrapping each small part of the commit phase into a guarded + // callback is a bit too slow (https://github.com/facebook/react/pull/21666). + // But we rely on it to surface errors to DEV tools like overlays + // (https://github.com/facebook/react/issues/21712). + // As a compromise, rethrow only caught errors in a guard. { - if ((workInProgress.mode & ProfileMode) !== NoMode) { - var isTimedOutSuspense = nextState !== null; + invokeGuardedCallback(null, function () { + throw error; + }); + clearCaughtError(); + } + } - if (isTimedOutSuspense) { - // Don't count time spent in a timed out Suspense subtree as part of the base duration. - var primaryChildFragment = workInProgress.child; + function callComponentWillUnmountWithTimer(current, instance) { + instance.props = current.memoizedProps; + instance.state = current.memoizedState; - if (primaryChildFragment !== null) { - // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - primaryChildFragment.treeBaseDuration; - } - } + if (shouldProfile(current)) { + try { + startLayoutEffectTimer(); + instance.componentWillUnmount(); + } finally { + recordLayoutEffectDuration(current); } + } else { + instance.componentWillUnmount(); } + } // Capture errors so they don't interrupt unmounting. - return false; - } else { - if ((workInProgress.flags & DidCapture) === NoFlags$1) { - // This boundary did not suspend so it's now hydrated and unsuspended. - workInProgress.memoizedState = null; - } // If nothing suspended, we need to schedule an effect to mark this boundary - // as having hydrated so events know that they're free to be invoked. - // It's also a signal to replay events and the suspense callback. - // If something suspended, schedule an effect to attach retry listeners. - // So we might as well always mark this. + function safelyCallComponentWillUnmount( + current, + nearestMountedAncestor, + instance + ) { + try { + callComponentWillUnmountWithTimer(current, instance); + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } + } // Capture errors so they don't interrupt mounting. - workInProgress.flags |= Update; - bubbleProperties(workInProgress); + function safelyAttachRef(current, nearestMountedAncestor) { + try { + commitAttachRef(current); + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } + } - { - if ((workInProgress.mode & ProfileMode) !== NoMode) { - var _isTimedOutSuspense = nextState !== null; + function safelyDetachRef(current, nearestMountedAncestor) { + var ref = current.ref; + var refCleanup = current.refCleanup; + + if (ref !== null) { + if (typeof refCleanup === "function") { + try { + if (shouldProfile(current)) { + try { + startLayoutEffectTimer(); + refCleanup(); + } finally { + recordLayoutEffectDuration(current); + } + } else { + refCleanup(); + } + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } finally { + // `refCleanup` has been called. Nullify all references to it to prevent double invocation. + current.refCleanup = null; + var finishedWork = current.alternate; - if (_isTimedOutSuspense) { - // Don't count time spent in a timed out Suspense subtree as part of the base duration. - var _primaryChildFragment = workInProgress.child; + if (finishedWork != null) { + finishedWork.refCleanup = null; + } + } + } else if (typeof ref === "function") { + var retVal; + + try { + if (shouldProfile(current)) { + try { + startLayoutEffectTimer(); + retVal = ref(null); + } finally { + recordLayoutEffectDuration(current); + } + } else { + retVal = ref(null); + } + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } - if (_primaryChildFragment !== null) { - // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - _primaryChildFragment.treeBaseDuration; + { + if (typeof retVal === "function") { + error( + "Unexpected return value from a callback ref in %s. " + + "A callback ref should not return a function.", + getComponentNameFromFiber(current) + ); } } + } else { + // $FlowFixMe[incompatible-use] unable to narrow type to RefObject + ref.current = null; } } - - return false; } - } else { - // Successfully completed this tree. If this was a forced client render, - // there may have been recoverable errors during first hydration - // attempt. If so, add them to a queue so we can log them in the - // commit phase. - upgradeHydrationErrorsToRecoverable(); // Fall through to normal Suspense path - return true; - } -} + function safelyCallDestroy(current, nearestMountedAncestor, destroy) { + try { + destroy(); + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } + } -function completeWork(current, workInProgress, renderLanes) { - var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing - - switch (workInProgress.tag) { - case IndeterminateComponent: - case LazyComponent: - case SimpleMemoComponent: - case FunctionComponent: - case ForwardRef: - case Fragment: - case Mode: - case Profiler: - case ContextConsumer: - case MemoComponent: - bubbleProperties(workInProgress); - return null; + var focusedInstanceHandle = null; + var shouldFireAfterActiveInstanceBlur = false; + function commitBeforeMutationEffects(root, firstChild) { + focusedInstanceHandle = prepareForCommit(); + nextEffect = firstChild; + commitBeforeMutationEffects_begin(); // We no longer need to track the active instance fiber - case ClassComponent: { - bubbleProperties(workInProgress); - return null; + var shouldFire = shouldFireAfterActiveInstanceBlur; + shouldFireAfterActiveInstanceBlur = false; + focusedInstanceHandle = null; + return shouldFire; } - case HostRoot: { - var fiberRoot = workInProgress.stateNode; + function commitBeforeMutationEffects_begin() { + while (nextEffect !== null) { + var fiber = nextEffect; // This phase is only used for beforeActiveInstanceBlur. + // Let's skip the whole loop if it's off. - if (enableTransitionTracing) { - var transitions = getWorkInProgressTransitions(); // We set the Passive flag here because if there are new transitions, - // we will need to schedule callbacks and process the transitions, - // which we do in the passive phase + { + // TODO: Should wrap this in flags check, too, as optimization + var deletions = fiber.deletions; - if (transitions !== null) { - workInProgress.flags |= Passive$1; + if (deletions !== null) { + for (var i = 0; i < deletions.length; i++) { + var deletion = deletions[i]; + commitBeforeMutationEffectsDeletion(deletion); + } + } } - } - { - var previousCache = null; + var child = fiber.child; - if (current !== null) { - previousCache = current.memoizedState.cache; + if ( + (fiber.subtreeFlags & BeforeMutationMask) !== NoFlags$1 && + child !== null + ) { + child.return = fiber; + nextEffect = child; + } else { + commitBeforeMutationEffects_complete(); } + } + } - var cache = workInProgress.memoizedState.cache; + function commitBeforeMutationEffects_complete() { + while (nextEffect !== null) { + var fiber = nextEffect; + setCurrentFiber(fiber); - if (cache !== previousCache) { - // Run passive effects to retain/release the cache. - workInProgress.flags |= Passive$1; + try { + commitBeforeMutationEffectsOnFiber(fiber); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); } - popCacheProvider(workInProgress); - } - - if (enableTransitionTracing) { - popRootMarkerInstance(workInProgress); - } + resetCurrentFiber(); + var sibling = fiber.sibling; - popRootTransition(workInProgress); - popHostContainer(workInProgress); + if (sibling !== null) { + sibling.return = fiber.return; + nextEffect = sibling; + return; + } - if (fiberRoot.pendingContext) { - fiberRoot.context = fiberRoot.pendingContext; - fiberRoot.pendingContext = null; + nextEffect = fiber.return; } + } - if (current === null || current.child === null) { - // If we hydrated, pop so that we can delete any remaining children - // that weren't hydrated. - var wasHydrated = popHydrationState(); - - if (wasHydrated) { - // If we hydrated, then we'll need to schedule an update for - // the commit side-effects on the root. - markUpdate(workInProgress); - } else { - if (current !== null) { - var prevState = current.memoizedState; - - if ( - // Check if this is a client root - !prevState.isDehydrated || // Check if we reverted to client rendering (e.g. due to an error) - (workInProgress.flags & ForceClientRender) !== NoFlags$1 - ) { - // Schedule an effect to clear this container at the start of the - // next commit. This handles the case of React rendering into a - // container with previous children. It's also safe to do for - // updates too, because current.child would only be null if the - // previous render was null (so the container would already - // be empty). - workInProgress.flags |= Snapshot; // If this was a forced client render, there may have been - // recoverable errors during first hydration attempt. If so, add - // them to a queue so we can log them in the commit phase. + function commitBeforeMutationEffectsOnFiber(finishedWork) { + var current = finishedWork.alternate; + var flags = finishedWork.flags; - upgradeHydrationErrorsToRecoverable(); - } + { + if ( + !shouldFireAfterActiveInstanceBlur && + focusedInstanceHandle !== null + ) { + // Check to see if the focused element was inside of a hidden (Suspense) subtree. + // TODO: Move this out of the hot path using a dedicated effect tag. + if ( + finishedWork.tag === SuspenseComponent && + isSuspenseBoundaryBeingHidden(current, finishedWork) && // $FlowFixMe[incompatible-call] found when upgrading Flow + doesFiberContain(finishedWork, focusedInstanceHandle) + ) { + shouldFireAfterActiveInstanceBlur = true; } } } - bubbleProperties(workInProgress); - if (enableTransitionTracing) { - if ((workInProgress.subtreeFlags & Visibility) !== NoFlags$1) { - // If any of our suspense children toggle visibility, this means that - // the pending boundaries array needs to be updated, which we only - // do in the passive phase. - workInProgress.flags |= Passive$1; - } + if ((flags & Snapshot) !== NoFlags$1) { + setCurrentFiber(finishedWork); } - return null; - } - - case HostHoistable: - - case HostSingleton: - - case HostComponent: { - popHostContext(workInProgress); - var _type2 = workInProgress.type; - - if (current !== null && workInProgress.stateNode != null) { - updateHostComponent(current, workInProgress, _type2, newProps); + switch (finishedWork.tag) { + case FunctionComponent: { + { + if ((flags & Update) !== NoFlags$1) { + commitUseEffectEventMount(finishedWork); + } + } - if (current.ref !== workInProgress.ref) { - markRef(workInProgress); + break; } - } else { - if (!newProps) { - if (workInProgress.stateNode === null) { - 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." - ); - } // This can happen when we abort work. - bubbleProperties(workInProgress); - return null; + case ForwardRef: + case SimpleMemoComponent: { + break; } - getHostContext(); // TODO: Move createInstance to beginWork and keep it on a context - // "stack" as the parent. Then append children as we go in beginWork - // or completeWork depending on whether we want to add them top->down or - // bottom->up. Top->down is faster in IE11. - - var _wasHydrated2 = popHydrationState(); - - if (_wasHydrated2) { - // TODO: Move this and createInstance step into the beginPhase - // to consolidate. - prepareToHydrateHostInstance(); - } else { - getRootHostContainer(); + case ClassComponent: { + if ((flags & Snapshot) !== NoFlags$1) { + if (current !== null) { + var prevProps = current.memoizedProps; + var prevState = current.memoizedState; + var instance = finishedWork.stateNode; // We could update instance props and state here, + // but instead we rely on them being set during last render. + // TODO: revisit this when we implement resuming. - var _instance3 = createInstance(_type2, newProps); // TODO: For persistent renderers, we should pass children as part - // of the initial instance creation + { + if ( + finishedWork.type === finishedWork.elementType && + !didWarnAboutReassigningProps + ) { + if (instance.props !== finishedWork.memoizedProps) { + 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" + ); + } - appendAllChildren(_instance3, workInProgress); - workInProgress.stateNode = _instance3; // Certain renderers require commit-time effects for initial mount. - } + if (instance.state !== finishedWork.memoizedState) { + 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" + ); + } + } + } - if (workInProgress.ref !== null) { - // If there is a ref on a host node we need to schedule a callback - markRef(workInProgress); - } - } + var snapshot = instance.getSnapshotBeforeUpdate( + finishedWork.elementType === finishedWork.type + ? prevProps + : resolveDefaultProps(finishedWork.type, prevProps), + prevState + ); - bubbleProperties(workInProgress); // This must come at the very end of the complete phase, because it might - // throw to suspend, and if the resource immediately loads, the work loop - // will resume rendering as if the work-in-progress completed. So it must - // fully complete. + { + var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate; - preloadInstanceAndSuspendIfNeeded(workInProgress); - return null; - } + if ( + snapshot === undefined && + !didWarnSet.has(finishedWork.type) + ) { + didWarnSet.add(finishedWork.type); - case HostText: { - var newText = newProps; + error( + "%s.getSnapshotBeforeUpdate(): A snapshot value (or null) " + + "must be returned. You have returned undefined.", + getComponentNameFromFiber(finishedWork) + ); + } + } - if (current && workInProgress.stateNode != null) { - var oldText = current.memoizedProps; // If we have an alternate, that means this is an update and we need - // to schedule a side-effect to do the updates. + instance.__reactInternalSnapshotBeforeUpdate = snapshot; + } + } - updateHostText(current, workInProgress, oldText, newText); - } else { - if (typeof newText !== "string") { - if (workInProgress.stateNode === null) { - 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." - ); - } // This can happen when we abort work. + break; } - getRootHostContainer(); - - getHostContext(); + case HostRoot: { + break; + } - var _wasHydrated3 = popHydrationState(); + case HostComponent: + case HostHoistable: + case HostSingleton: + case HostText: + case HostPortal: + case IncompleteClassComponent: + // Nothing to do for these component types + break; - if (_wasHydrated3) { - if (prepareToHydrateHostTextInstance()) { - markUpdate(workInProgress); + default: { + if ((flags & Snapshot) !== NoFlags$1) { + 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." + ); } - } else { - workInProgress.stateNode = createTextInstance(newText); } } - bubbleProperties(workInProgress); - return null; + if ((flags & Snapshot) !== NoFlags$1) { + resetCurrentFiber(); + } } - case SuspenseComponent: { - popSuspenseHandler(workInProgress); - var nextState = workInProgress.memoizedState; // Special path for dehydrated boundaries. We may eventually move this - // to its own fiber type so that we can add other kinds of hydration - // boundaries that aren't associated with a Suspense tree. In anticipation - // of such a refactor, all the hydration logic is contained in - // this branch. - - if ( - current === null || - (current.memoizedState !== null && - current.memoizedState.dehydrated !== null) - ) { - var fallthroughToNormalSuspensePath = - completeDehydratedSuspenseBoundary( - current, - workInProgress, - nextState - ); - - if (!fallthroughToNormalSuspensePath) { - if (workInProgress.flags & ForceClientRender) { - // Special case. There were remaining unhydrated nodes. We treat - // this as a mismatch. Revert to client rendering. - return workInProgress; - } else { - // Did not finish hydrating, either because this is the initial - // render or because something suspended. - return null; - } - } // Continue with the normal Suspense path. + function commitBeforeMutationEffectsDeletion(deletion) { + { + // TODO (effects) It would be nice to avoid calling doesFiberContain() + // Maybe we can repurpose one of the subtreeFlags positions for this instead? + // Use it to store which part of the tree the focused instance is in? + // This assumes we can safely determine that instance during the "render" phase. + if (doesFiberContain(deletion, focusedInstanceHandle)) { + shouldFireAfterActiveInstanceBlur = true; + } } + } - if ((workInProgress.flags & DidCapture) !== NoFlags$1) { - // Something suspended. Re-render with the fallback children. - workInProgress.lanes = renderLanes; // Do not reset the effect list. + function commitHookEffectListUnmount( + flags, + finishedWork, + nearestMountedAncestor + ) { + var updateQueue = finishedWork.updateQueue; + var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); - } // Don't bubble properties in this case. + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; - return workInProgress; - } + do { + if ((effect.tag & flags) === flags) { + // Unmount + var inst = effect.inst; + var destroy = inst.destroy; + + if (destroy !== undefined) { + inst.destroy = undefined; + + if (enableSchedulingProfiler) { + if ((flags & Passive) !== NoFlags) { + markComponentPassiveEffectUnmountStarted(finishedWork); + } else if ((flags & Layout) !== NoFlags) { + markComponentLayoutEffectUnmountStarted(finishedWork); + } + } - var nextDidTimeout = nextState !== null; - var prevDidTimeout = current !== null && current.memoizedState !== null; + { + if ((flags & Insertion) !== NoFlags) { + setIsRunningInsertionEffect(true); + } + } - if (nextDidTimeout) { - var offscreenFiber = workInProgress.child; - var _previousCache = null; + safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy); - if ( - offscreenFiber.alternate !== null && - offscreenFiber.alternate.memoizedState !== null && - offscreenFiber.alternate.memoizedState.cachePool !== null - ) { - _previousCache = - offscreenFiber.alternate.memoizedState.cachePool.pool; - } + { + if ((flags & Insertion) !== NoFlags) { + setIsRunningInsertionEffect(false); + } + } - var _cache = null; + if (enableSchedulingProfiler) { + if ((flags & Passive) !== NoFlags) { + markComponentPassiveEffectUnmountStopped(); + } else if ((flags & Layout) !== NoFlags) { + markComponentLayoutEffectUnmountStopped(); + } + } + } + } - if ( - offscreenFiber.memoizedState !== null && - offscreenFiber.memoizedState.cachePool !== null - ) { - _cache = offscreenFiber.memoizedState.cachePool.pool; - } + effect = effect.next; + } while (effect !== firstEffect); + } + } - if (_cache !== _previousCache) { - // Run passive effects to retain/release the cache. - offscreenFiber.flags |= Passive$1; - } - } // If the suspended state of the boundary changes, we need to schedule - // a passive effect, which is when we process the transitions + function commitHookEffectListMount(flags, finishedWork) { + var updateQueue = finishedWork.updateQueue; + var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; - if (nextDidTimeout !== prevDidTimeout) { - if (enableTransitionTracing) { - var _offscreenFiber = workInProgress.child; - _offscreenFiber.flags |= Passive$1; - } // If the suspended state of the boundary changes, we need to schedule - // an effect to toggle the subtree's visibility. When we switch from - // fallback -> primary, the inner Offscreen fiber schedules this effect - // as part of its normal complete phase. But when we switch from - // primary -> fallback, the inner Offscreen fiber does not have a complete - // phase. So we need to schedule its effect here. - // - // We also use this flag to connect/disconnect the effects, but the same - // logic applies: when re-connecting, the Offscreen fiber's complete - // phase will handle scheduling the effect. It's only when the fallback - // is active that we have to do anything special. + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; - if (nextDidTimeout) { - var _offscreenFiber2 = workInProgress.child; - _offscreenFiber2.flags |= Visibility; - } - } + do { + if ((effect.tag & flags) === flags) { + if (enableSchedulingProfiler) { + if ((flags & Passive) !== NoFlags) { + markComponentPassiveEffectMountStarted(finishedWork); + } else if ((flags & Layout) !== NoFlags) { + markComponentLayoutEffectMountStarted(finishedWork); + } + } // Mount - var retryQueue = workInProgress.updateQueue; - scheduleRetryEffect(workInProgress, retryQueue); + var create = effect.create; - if ( - workInProgress.updateQueue !== null && - workInProgress.memoizedProps.suspenseCallback != null - ) { - // Always notify the callback - // TODO: Move to passive phase - workInProgress.flags |= Update; - } + { + if ((flags & Insertion) !== NoFlags) { + setIsRunningInsertionEffect(true); + } + } - bubbleProperties(workInProgress); + var inst = effect.inst; + var destroy = create(); + inst.destroy = destroy; - { - if ((workInProgress.mode & ProfileMode) !== NoMode) { - if (nextDidTimeout) { - // Don't count time spent in a timed out Suspense subtree as part of the base duration. - var primaryChildFragment = workInProgress.child; + { + if ((flags & Insertion) !== NoFlags) { + setIsRunningInsertionEffect(false); + } + } - if (primaryChildFragment !== null) { - // $FlowFixMe[unsafe-arithmetic] Flow doesn't support type casting in combination with the -= operator - workInProgress.treeBaseDuration -= - primaryChildFragment.treeBaseDuration; + if (enableSchedulingProfiler) { + if ((flags & Passive) !== NoFlags) { + markComponentPassiveEffectMountStopped(); + } else if ((flags & Layout) !== NoFlags) { + markComponentLayoutEffectMountStopped(); + } } - } - } - } - return null; - } + { + if (destroy !== undefined && typeof destroy !== "function") { + var hookName = void 0; - case HostPortal: - popHostContainer(workInProgress); + if ((effect.tag & Layout) !== NoFlags$1) { + hookName = "useLayoutEffect"; + } else if ((effect.tag & Insertion) !== NoFlags$1) { + hookName = "useInsertionEffect"; + } else { + hookName = "useEffect"; + } - bubbleProperties(workInProgress); - return null; + var addendum = void 0; + + if (destroy === null) { + addendum = + " You returned null. If your effect does not require clean " + + "up, return undefined (or nothing)."; + } else if (typeof destroy.then === "function") { + 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"; + } else { + addendum = " You returned: " + destroy; + } - case ContextProvider: - // Pop provider fiber - var context = workInProgress.type._context; - popProvider(context, workInProgress); - bubbleProperties(workInProgress); - return null; + error( + "%s must not return anything besides a function, " + + "which is used for clean-up.%s", + hookName, + addendum + ); + } + } + } - case IncompleteClassComponent: { - bubbleProperties(workInProgress); - return null; + effect = effect.next; + } while (effect !== firstEffect); + } } - case SuspenseListComponent: { - popSuspenseListContext(workInProgress); - var renderState = workInProgress.memoizedState; + function commitUseEffectEventMount(finishedWork) { + var updateQueue = finishedWork.updateQueue; + var eventPayloads = updateQueue !== null ? updateQueue.events : null; - if (renderState === null) { - // We're running in the default, "independent" mode. - // We don't do anything in this mode. - bubbleProperties(workInProgress); - return null; + if (eventPayloads !== null) { + for (var ii = 0; ii < eventPayloads.length; ii++) { + var _eventPayloads$ii = eventPayloads[ii], + ref = _eventPayloads$ii.ref, + nextImpl = _eventPayloads$ii.nextImpl; + ref.impl = nextImpl; + } } + } - var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags$1; - var renderedTail = renderState.rendering; - - if (renderedTail === null) { - // We just rendered the head. - if (!didSuspendAlready) { - // This is the first pass. We need to figure out if anything is still - // suspended in the rendered set. - // If new content unsuspended, but there's still some content that - // didn't. Then we need to do a second pass that forces everything - // to keep showing their fallbacks. - // We might be suspended if something in this render pass suspended, or - // something in the previous committed pass suspended. Otherwise, - // there's no chance so we can skip the expensive call to - // findFirstSuspended. - var cannotBeSuspended = - renderHasNotSuspendedYet() && - (current === null || (current.flags & DidCapture) === NoFlags$1); - - if (!cannotBeSuspended) { - var row = workInProgress.child; + function commitPassiveEffectDurations(finishedRoot, finishedWork) { + if (getExecutionContext() & CommitContext) { + // Only Profilers with work in their subtree will have an Update effect scheduled. + if ((finishedWork.flags & Update) !== NoFlags$1) { + switch (finishedWork.tag) { + case Profiler: { + var passiveEffectDuration = + finishedWork.stateNode.passiveEffectDuration; + var _finishedWork$memoize = finishedWork.memoizedProps, + id = _finishedWork$memoize.id, + onPostCommit = _finishedWork$memoize.onPostCommit; // This value will still reflect the previous commit phase. + // It does not get reset until the start of the next commit phase. - while (row !== null) { - var suspended = findFirstSuspended(row); + var commitTime = getCommitTime(); + var phase = finishedWork.alternate === null ? "mount" : "update"; - if (suspended !== null) { - didSuspendAlready = true; - workInProgress.flags |= DidCapture; - cutOffTailIfNeeded(renderState, false); // If this is a newly suspended tree, it might not get committed as - // part of the second pass. In that case nothing will subscribe to - // its thenables. Instead, we'll transfer its thenables to the - // SuspenseList so that it can retry if they resolve. - // There might be multiple of these in the list but since we're - // going to wait for all of them anyway, it doesn't really matter - // which ones gets to ping. In theory we could get clever and keep - // track of how many dependencies remain but it gets tricky because - // in the meantime, we can add/remove/change items and dependencies. - // We might bail out of the loop before finding any but that - // doesn't matter since that means that the other boundaries that - // we did find already has their listeners attached. - - var _retryQueue = suspended.updateQueue; - workInProgress.updateQueue = _retryQueue; - scheduleRetryEffect(workInProgress, _retryQueue); // Rerender the whole list, but this time, we'll force fallbacks - // to stay in place. - // Reset the effect flags before doing the second pass since that's now invalid. - // Reset the child fibers to their original state. - - workInProgress.subtreeFlags = NoFlags$1; - resetChildFibers(workInProgress, renderLanes); // Set up the Suspense List Context to force suspense and - // immediately rerender the children. - - pushSuspenseListContext( - workInProgress, - setShallowSuspenseListContext( - suspenseStackCursor.current, - ForceSuspenseFallback - ) - ); // Don't bubble properties in this case. - - return workInProgress.child; + { + if (isCurrentUpdateNested()) { + phase = "nested-update"; + } } - row = row.sibling; - } - } - - if (renderState.tail !== null && now$1() > getRenderTargetTime()) { - // We have already passed our CPU deadline but we still have rows - // left in the tail. We'll just give up further attempts to render - // the main content and only render fallbacks. - workInProgress.flags |= DidCapture; - didSuspendAlready = true; - cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this - // to get it started back up to attempt the next item. While in terms - // of priority this work has the same priority as this current render, - // it's not part of the same transition once the transition has - // committed. If it's sync, we still want to yield so that it can be - // painted. Conceptually, this is really the same as pinging. - // We can use any RetryLane even if it's the one currently rendering - // since we're leaving it behind on this node. - - workInProgress.lanes = SomeRetryLane; - } - } else { - cutOffTailIfNeeded(renderState, false); - } // Next we're going to render the tail. - } else { - // Append the rendered row to the child list. - if (!didSuspendAlready) { - var _suspended = findFirstSuspended(renderedTail); - - if (_suspended !== null) { - workInProgress.flags |= DidCapture; - didSuspendAlready = true; // Ensure we transfer the update queue to the parent so that it doesn't - // get lost if this row ends up dropped during a second pass. + if (typeof onPostCommit === "function") { + onPostCommit(id, phase, passiveEffectDuration, commitTime); + } // Bubble times to the next nearest ancestor Profiler. + // After we process that Profiler, we'll bubble further up. + + var parentFiber = finishedWork.return; + + outer: while (parentFiber !== null) { + switch (parentFiber.tag) { + case HostRoot: + var root = parentFiber.stateNode; + root.passiveEffectDuration += passiveEffectDuration; + break outer; + + case Profiler: + var parentStateNode = parentFiber.stateNode; + parentStateNode.passiveEffectDuration += + passiveEffectDuration; + break outer; + } - var _retryQueue2 = _suspended.updateQueue; - workInProgress.updateQueue = _retryQueue2; - scheduleRetryEffect(workInProgress, _retryQueue2); - cutOffTailIfNeeded(renderState, true); // This might have been modified. + parentFiber = parentFiber.return; + } - if ( - renderState.tail === null && - renderState.tailMode === "hidden" && - !renderedTail.alternate && - !getIsHydrating() // We don't cut it if we're hydrating. - ) { - // We're done. - bubbleProperties(workInProgress); - return null; + break; } - } else if ( - // The time it took to render last row is greater than the remaining - // time we have to render. So rendering one more row would likely - // exceed it. - now$1() * 2 - renderState.renderingStartTime > - getRenderTargetTime() && - renderLanes !== OffscreenLane - ) { - // We have now passed our CPU deadline and we'll just give up further - // attempts to render the main content and only render fallbacks. - // The assumption is that this is usually faster. - workInProgress.flags |= DidCapture; - didSuspendAlready = true; - cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this - // to get it started back up to attempt the next item. While in terms - // of priority this work has the same priority as this current render, - // it's not part of the same transition once the transition has - // committed. If it's sync, we still want to yield so that it can be - // painted. Conceptually, this is really the same as pinging. - // We can use any RetryLane even if it's the one currently rendering - // since we're leaving it behind on this node. - - workInProgress.lanes = SomeRetryLane; - } - } - - if (renderState.isBackwards) { - // The effect list of the backwards tail will have been added - // to the end. This breaks the guarantee that life-cycles fire in - // sibling order but that isn't a strong guarantee promised by React. - // Especially since these might also just pop in during future commits. - // Append to the beginning of the list. - renderedTail.sibling = workInProgress.child; - workInProgress.child = renderedTail; - } else { - var previousSibling = renderState.last; - - if (previousSibling !== null) { - previousSibling.sibling = renderedTail; - } else { - workInProgress.child = renderedTail; } - - renderState.last = renderedTail; } } + } - if (renderState.tail !== null) { - // We still have tail rows to render. - // Pop a row. - var next = renderState.tail; - renderState.rendering = next; - renderState.tail = next.sibling; - renderState.renderingStartTime = now$1(); - next.sibling = null; // Restore the context. - // TODO: We can probably just avoid popping it instead and only - // setting it the first time we go from not suspended to suspended. - - var suspenseContext = suspenseStackCursor.current; - - if (didSuspendAlready) { - suspenseContext = setShallowSuspenseListContext( - suspenseContext, - ForceSuspenseFallback - ); - } else { - suspenseContext = - setDefaultShallowSuspenseListContext(suspenseContext); + function commitHookLayoutEffects(finishedWork, hookFlags) { + // At this point layout effects have already been destroyed (during mutation phase). + // This is done to prevent sibling component effects from interfering with each other, + // e.g. a destroy function in one component should never override a ref set + // by a create function in another component during the same commit. + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + commitHookEffectListMount(hookFlags, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } - pushSuspenseListContext(workInProgress, suspenseContext); // Do a pass over the next row. - // Don't bubble properties in this case. - - return next; + recordLayoutEffectDuration(finishedWork); + } else { + try { + commitHookEffectListMount(hookFlags, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } } - - bubbleProperties(workInProgress); - return null; } - case ScopeComponent: { - { - if (current === null) { - var scopeInstance = createScopeInstance(); - workInProgress.stateNode = scopeInstance; - prepareScopeUpdate(); + function commitClassLayoutLifecycles(finishedWork, current) { + var instance = finishedWork.stateNode; + + if (current === null) { + // We could update instance props and state here, + // but instead we rely on them being set during last render. + // TODO: revisit this when we implement resuming. + { + if ( + finishedWork.type === finishedWork.elementType && + !didWarnAboutReassigningProps + ) { + if (instance.props !== finishedWork.memoizedProps) { + 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" + ); + } - if (workInProgress.ref !== null) { - markRef(workInProgress); - markUpdate(workInProgress); + if (instance.state !== finishedWork.memoizedState) { + 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" + ); + } } - } else { - if (workInProgress.ref !== null) { - markUpdate(workInProgress); + } + + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + instance.componentDidMount(); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } - if (current.ref !== workInProgress.ref) { - markRef(workInProgress); + recordLayoutEffectDuration(finishedWork); + } else { + try { + instance.componentDidMount(); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } } + } else { + var prevProps = + finishedWork.elementType === finishedWork.type + ? current.memoizedProps + : resolveDefaultProps(finishedWork.type, current.memoizedProps); + var prevState = current.memoizedState; // We could update instance props and state here, + // but instead we rely on them being set during last render. + // TODO: revisit this when we implement resuming. - bubbleProperties(workInProgress); - return null; - } - } - - case OffscreenComponent: - case LegacyHiddenComponent: { - popSuspenseHandler(workInProgress); - popHiddenContext(workInProgress); - var _nextState = workInProgress.memoizedState; - var nextIsHidden = _nextState !== null; // Schedule a Visibility effect if the visibility has changed + { + if ( + finishedWork.type === finishedWork.elementType && + !didWarnAboutReassigningProps + ) { + if (instance.props !== finishedWork.memoizedProps) { + 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" + ); + } - if (workInProgress.tag === LegacyHiddenComponent); - else { - if (current !== null) { - var _prevState = current.memoizedState; - var prevIsHidden = _prevState !== null; + if (instance.state !== finishedWork.memoizedState) { + 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" + ); + } + } + } - if (prevIsHidden !== nextIsHidden) { - workInProgress.flags |= Visibility; + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + instance.componentDidUpdate( + prevProps, + prevState, + instance.__reactInternalSnapshotBeforeUpdate + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } + + recordLayoutEffectDuration(finishedWork); } else { - // On initial mount, we only need a Visibility effect if the tree - // is hidden. - if (nextIsHidden) { - workInProgress.flags |= Visibility; + try { + instance.componentDidUpdate( + prevProps, + prevState, + instance.__reactInternalSnapshotBeforeUpdate + ); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } } } + } - if (!nextIsHidden || (workInProgress.mode & ConcurrentMode) === NoMode) { - bubbleProperties(workInProgress); - } else { - // Don't bubble properties for hidden children unless we're rendering - // at offscreen priority. - if ( - includesSomeLane(renderLanes, OffscreenLane) && // Also don't bubble if the tree suspended - (workInProgress.flags & DidCapture) === NoLanes - ) { - bubbleProperties(workInProgress); // Check if there was an insertion or update in the hidden subtree. - // If so, we need to hide those nodes in the commit phase, so - // schedule a visibility effect. + function commitClassCallbacks(finishedWork) { + // TODO: I think this is now always non-null by the time it reaches the + // commit phase. Consider removing the type check. + var updateQueue = finishedWork.updateQueue; + + if (updateQueue !== null) { + var instance = finishedWork.stateNode; + { if ( - workInProgress.tag !== LegacyHiddenComponent && - workInProgress.subtreeFlags & (Placement | Update) + finishedWork.type === finishedWork.elementType && + !didWarnAboutReassigningProps ) { - workInProgress.flags |= Visibility; + if (instance.props !== finishedWork.memoizedProps) { + 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" + ); + } + + if (instance.state !== finishedWork.memoizedState) { + 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" + ); + } } + } // We could update instance props and state here, + // but instead we rely on them being set during last render. + // TODO: revisit this when we implement resuming. + + try { + commitCallbacks(updateQueue, instance); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } } + } - var offscreenQueue = workInProgress.updateQueue; + function commitHostComponentMount(finishedWork) { + var type = finishedWork.type; + var props = finishedWork.memoizedProps; + var instance = finishedWork.stateNode; - if (offscreenQueue !== null) { - var _retryQueue3 = offscreenQueue.retryQueue; - scheduleRetryEffect(workInProgress, _retryQueue3); + try { + commitMount(instance, type, props, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } + } - { - var _previousCache2 = null; + function commitProfilerUpdate(finishedWork, current) { + if (getExecutionContext() & CommitContext) { + try { + var _finishedWork$memoize2 = finishedWork.memoizedProps, + onCommit = _finishedWork$memoize2.onCommit, + onRender = _finishedWork$memoize2.onRender; + var effectDuration = finishedWork.stateNode.effectDuration; + var commitTime = getCommitTime(); + var phase = current === null ? "mount" : "update"; - if ( - current !== null && - current.memoizedState !== null && - current.memoizedState.cachePool !== null - ) { - _previousCache2 = current.memoizedState.cachePool.pool; - } + if (enableProfilerNestedUpdatePhase) { + if (isCurrentUpdateNested()) { + phase = "nested-update"; + } + } - var _cache2 = null; + if (typeof onRender === "function") { + onRender( + finishedWork.memoizedProps.id, + phase, + finishedWork.actualDuration, + finishedWork.treeBaseDuration, + finishedWork.actualStartTime, + commitTime + ); + } - if ( - workInProgress.memoizedState !== null && - workInProgress.memoizedState.cachePool !== null - ) { - _cache2 = workInProgress.memoizedState.cachePool.pool; - } + if (enableProfilerCommitHooks) { + if (typeof onCommit === "function") { + onCommit( + finishedWork.memoizedProps.id, + phase, + effectDuration, + commitTime + ); + } // Schedule a passive effect for this Profiler to call onPostCommit hooks. + // This effect should be scheduled even if there is no onPostCommit callback for this Profiler, + // because the effect is also where times bubble to parent Profilers. + + enqueuePendingPassiveProfilerEffect(finishedWork); // Propagate layout effect durations to the next nearest Profiler ancestor. + // Do not reset these values until the next render so DevTools has a chance to read them first. + + var parentFiber = finishedWork.return; + + outer: while (parentFiber !== null) { + switch (parentFiber.tag) { + case HostRoot: + var root = parentFiber.stateNode; + root.effectDuration += effectDuration; + break outer; + + case Profiler: + var parentStateNode = parentFiber.stateNode; + parentStateNode.effectDuration += effectDuration; + break outer; + } - if (_cache2 !== _previousCache2) { - // Run passive effects to retain/release the cache. - workInProgress.flags |= Passive$1; + parentFiber = parentFiber.return; + } + } + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); } } - - popTransition(workInProgress, current); - return null; } - case CacheComponent: { - { - var _previousCache3 = null; - - if (current !== null) { - _previousCache3 = current.memoizedState.cache; - } - - var _cache3 = workInProgress.memoizedState.cache; - - if (_cache3 !== _previousCache3) { - // Run passive effects to retain/release the cache. - workInProgress.flags |= Passive$1; - } - - popCacheProvider(workInProgress); - bubbleProperties(workInProgress); - } + function commitLayoutEffectOnFiber( + finishedRoot, + current, + finishedWork, + committedLanes + ) { + // When updating this function, also update reappearLayoutEffects, which does + // most of the same things when an offscreen tree goes from hidden -> visible. + var flags = finishedWork.flags; - return null; - } + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - case TracingMarkerComponent: { - if (enableTransitionTracing) { - var _instance4 = workInProgress.stateNode; + if (flags & Update) { + commitHookLayoutEffects(finishedWork, Layout | HasEffect); + } - if (_instance4 !== null) { - popMarkerInstance(workInProgress); + break; } - bubbleProperties(workInProgress); - } - - return null; - } - } + case ClassComponent: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - throw new Error( - "Unknown unit of work tag (" + - workInProgress.tag + - "). This error is likely caused by a bug in " + - "React. Please file an issue." - ); -} + if (flags & Update) { + commitClassLayoutLifecycles(finishedWork, current); + } -function unwindWork(current, workInProgress, renderLanes) { - switch (workInProgress.tag) { - case ClassComponent: { - var flags = workInProgress.flags; + if (flags & Callback) { + commitClassCallbacks(finishedWork); + } - if (flags & ShouldCapture) { - workInProgress.flags = (flags & ~ShouldCapture) | DidCapture; + if (flags & Ref) { + safelyAttachRef(finishedWork, finishedWork.return); + } - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); + break; } - return workInProgress; - } - - return null; - } - - case HostRoot: { - { - popCacheProvider(workInProgress); - } + case HostRoot: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + + if (flags & Callback) { + // TODO: I think this is now always non-null by the time it reaches the + // commit phase. Consider removing the type check. + var updateQueue = finishedWork.updateQueue; + + if (updateQueue !== null) { + var instance = null; + + if (finishedWork.child !== null) { + switch (finishedWork.child.tag) { + case HostSingleton: + case HostComponent: + instance = getPublicInstance(finishedWork.child.stateNode); + break; + + case ClassComponent: + instance = finishedWork.child.stateNode; + break; + } + } - if (enableTransitionTracing) { - popRootMarkerInstance(workInProgress); - } + try { + commitCallbacks(updateQueue, instance); + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } + } + } - popRootTransition(workInProgress); - popHostContainer(workInProgress); - var _flags = workInProgress.flags; + break; + } - if ( - (_flags & ShouldCapture) !== NoFlags$1 && - (_flags & DidCapture) === NoFlags$1 - ) { - // There was an error during render that wasn't captured by a suspense - // boundary. Do a second pass on the root to unmount the children. - workInProgress.flags = (_flags & ~ShouldCapture) | DidCapture; - return workInProgress; - } // We unwound to the root without completing it. Exit. + case HostHoistable: - return null; - } + case HostSingleton: + case HostComponent: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); // Renderers may schedule work to be done after host components are mounted + // (eg DOM renderer may schedule auto-focus for inputs and form controls). + // These effects should only be committed when components are first mounted, + // aka when there is no current/alternate. - case HostHoistable: - case HostSingleton: - case HostComponent: { - // TODO: popHydrationState - popHostContext(workInProgress); - return null; - } + if (current === null && flags & Update) { + commitHostComponentMount(finishedWork); + } - case SuspenseComponent: { - popSuspenseHandler(workInProgress); - var suspenseState = workInProgress.memoizedState; + if (flags & Ref) { + safelyAttachRef(finishedWork, finishedWork.return); + } - if (suspenseState !== null && suspenseState.dehydrated !== null) { - if (workInProgress.alternate === null) { - throw new Error( - "Threw in newly mounted dehydrated component. This is likely a bug in " + - "React. Please file an issue." - ); + break; } - } - var _flags2 = workInProgress.flags; + case Profiler: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); // TODO: Should this fire inside an offscreen tree? Or should it wait to + // fire when the tree becomes visible again. - if (_flags2 & ShouldCapture) { - workInProgress.flags = (_flags2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. + if (flags & Update) { + commitProfilerUpdate(finishedWork, current); + } - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); + break; } - return workInProgress; - } + case SuspenseComponent: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - return null; - } + break; + } - case SuspenseListComponent: { - popSuspenseListContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been - // caught by a nested boundary. If not, it should bubble through. + case OffscreenComponent: { + var isModernRoot = (finishedWork.mode & ConcurrentMode) !== NoMode; - return null; - } + if (isModernRoot) { + var isHidden = finishedWork.memoizedState !== null; + var newOffscreenSubtreeIsHidden = + isHidden || offscreenSubtreeIsHidden; - case HostPortal: - popHostContainer(workInProgress); - return null; + if (newOffscreenSubtreeIsHidden); + else { + // The Offscreen tree is visible. + var wasHidden = + current !== null && current.memoizedState !== null; + var newOffscreenSubtreeWasHidden = + wasHidden || offscreenSubtreeWasHidden; + var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden; + var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; + offscreenSubtreeIsHidden = newOffscreenSubtreeIsHidden; + offscreenSubtreeWasHidden = newOffscreenSubtreeWasHidden; + + if (offscreenSubtreeWasHidden && !prevOffscreenSubtreeWasHidden) { + // This is the root of a reappearing boundary. As we continue + // traversing the layout effects, we must also re-mount layout + // effects that were unmounted when the Offscreen subtree was + // hidden. So this is a superset of the normal commitLayoutEffects. + var includeWorkInProgressEffects = + (finishedWork.subtreeFlags & LayoutMask) !== NoFlags$1; + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); + } else { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + } - case ContextProvider: - var context = workInProgress.type._context; - popProvider(context, workInProgress); - return null; + offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; + offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; + } + } else { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + } - case OffscreenComponent: - case LegacyHiddenComponent: { - popSuspenseHandler(workInProgress); - popHiddenContext(workInProgress); - popTransition(workInProgress, current); - var _flags3 = workInProgress.flags; + if (flags & Ref) { + var props = finishedWork.memoizedProps; - if (_flags3 & ShouldCapture) { - workInProgress.flags = (_flags3 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. + if (props.mode === "manual") { + safelyAttachRef(finishedWork, finishedWork.return); + } else { + safelyDetachRef(finishedWork, finishedWork.return); + } + } - if ((workInProgress.mode & ProfileMode) !== NoMode) { - transferActualDuration(workInProgress); + break; } - return workInProgress; + default: { + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + break; + } } - - return null; } - case CacheComponent: - { - popCacheProvider(workInProgress); - } - - return null; - - case TracingMarkerComponent: + function abortRootTransitions( + root, + abort, + deletedTransitions, + deletedOffscreenInstance, + isInDeletedTree + ) { if (enableTransitionTracing) { - if (workInProgress.stateNode !== null) { - popMarkerInstance(workInProgress); - } - } - - return null; + var rootTransitions = root.incompleteTransitions; + deletedTransitions.forEach(function (transition) { + if (rootTransitions.has(transition)) { + var transitionInstance = rootTransitions.get(transition); - default: - return null; - } -} + if (transitionInstance.aborts === null) { + transitionInstance.aborts = []; + } -function unwindInterruptedWork(current, interruptedWork, renderLanes) { - switch (interruptedWork.tag) { - case ClassComponent: { - break; - } + transitionInstance.aborts.push(abort); - case HostRoot: { - { - popCacheProvider(interruptedWork); + if (deletedOffscreenInstance !== null) { + if ( + transitionInstance.pendingBoundaries !== null && + transitionInstance.pendingBoundaries.has( + deletedOffscreenInstance + ) + ) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + transitionInstance.pendingBoundaries.delete( + deletedOffscreenInstance + ); + } + } + } + }); } + } + function abortTracingMarkerTransitions( + abortedFiber, + abort, + deletedTransitions, + deletedOffscreenInstance, + isInDeletedTree + ) { if (enableTransitionTracing) { - popRootMarkerInstance(interruptedWork); + var markerInstance = abortedFiber.stateNode; + var markerTransitions = markerInstance.transitions; + var pendingBoundaries = markerInstance.pendingBoundaries; + + if (markerTransitions !== null) { + // TODO: Refactor this code. Is there a way to move this code to + // the deletions phase instead of calculating it here while making sure + // complete is called appropriately? + deletedTransitions.forEach(function (transition) { + // If one of the transitions on the tracing marker is a transition + // that was in an aborted subtree, we will abort that tracing marker + if ( + abortedFiber !== null && + markerTransitions.has(transition) && + (markerInstance.aborts === null || + !markerInstance.aborts.includes(abort)) + ) { + if (markerInstance.transitions !== null) { + if (markerInstance.aborts === null) { + markerInstance.aborts = [abort]; + addMarkerIncompleteCallbackToPendingTransition( + abortedFiber.memoizedProps.name, + markerInstance.transitions, + markerInstance.aborts + ); + } else { + markerInstance.aborts.push(abort); + } // We only want to call onTransitionProgress when the marker hasn't been + // deleted + + if ( + deletedOffscreenInstance !== null && + !isInDeletedTree && + pendingBoundaries !== null && + pendingBoundaries.has(deletedOffscreenInstance) + ) { + pendingBoundaries.delete(deletedOffscreenInstance); + addMarkerProgressCallbackToPendingTransition( + abortedFiber.memoizedProps.name, + deletedTransitions, + pendingBoundaries + ); + } + } + } + }); + } } - - popRootTransition(interruptedWork); - popHostContainer(interruptedWork); - break; - } - - case HostHoistable: - case HostSingleton: - case HostComponent: { - popHostContext(interruptedWork); - break; } - case HostPortal: - popHostContainer(interruptedWork); - break; - - case SuspenseComponent: - popSuspenseHandler(interruptedWork); - break; - - case SuspenseListComponent: - popSuspenseListContext(interruptedWork); - break; - - case ContextProvider: - var context = interruptedWork.type._context; - popProvider(context, interruptedWork); - break; + function abortParentMarkerTransitionsForDeletedFiber( + abortedFiber, + abort, + deletedTransitions, + deletedOffscreenInstance, + isInDeletedTree + ) { + if (enableTransitionTracing) { + // Find all pending markers that are waiting on child suspense boundaries in the + // aborted subtree and cancels them + var fiber = abortedFiber; + + while (fiber !== null) { + switch (fiber.tag) { + case TracingMarkerComponent: + abortTracingMarkerTransitions( + fiber, + abort, + deletedTransitions, + deletedOffscreenInstance, + isInDeletedTree + ); + break; - case OffscreenComponent: - case LegacyHiddenComponent: - popSuspenseHandler(interruptedWork); - popHiddenContext(interruptedWork); - popTransition(interruptedWork, current); - break; + case HostRoot: + var root = fiber.stateNode; + abortRootTransitions( + root, + abort, + deletedTransitions, + deletedOffscreenInstance + ); + break; + } - case CacheComponent: - { - popCacheProvider(interruptedWork); + fiber = fiber.return; + } } + } - break; - - case TracingMarkerComponent: + function commitTransitionProgress(offscreenFiber) { if (enableTransitionTracing) { - var instance = interruptedWork.stateNode; + // This function adds suspense boundaries to the root + // or tracing marker's pendingBoundaries map. + // When a suspense boundary goes from a resolved to a fallback + // state we add the boundary to the map, and when it goes from + // a fallback to a resolved state, we remove the boundary from + // the map. + // We use stateNode on the Offscreen component as a stable object + // that doesnt change from render to render. This way we can + // distinguish between different Offscreen instances (vs. the same + // Offscreen instance with different fibers) + var offscreenInstance = offscreenFiber.stateNode; + var prevState = null; + var previousFiber = offscreenFiber.alternate; + + if (previousFiber !== null && previousFiber.memoizedState !== null) { + prevState = previousFiber.memoizedState; + } + + var nextState = offscreenFiber.memoizedState; + var wasHidden = prevState !== null; + var isHidden = nextState !== null; + var pendingMarkers = offscreenInstance._pendingMarkers; // If there is a name on the suspense boundary, store that in + // the pending boundaries. + + var name = null; + var parent = offscreenFiber.return; - if (instance !== null) { - popMarkerInstance(interruptedWork); + if ( + parent !== null && + parent.tag === SuspenseComponent && + parent.memoizedProps.unstable_name + ) { + name = parent.memoizedProps.unstable_name; } - } - break; - } -} - -// Provided by www -var ReactFbErrorUtils = require("ReactFbErrorUtils"); + if (!wasHidden && isHidden) { + // The suspense boundaries was just hidden. Add the boundary + // to the pending boundary set if it's there + if (pendingMarkers !== null) { + pendingMarkers.forEach(function (markerInstance) { + var pendingBoundaries = markerInstance.pendingBoundaries; + var transitions = markerInstance.transitions; + var markerName = markerInstance.name; -if (typeof ReactFbErrorUtils.invokeGuardedCallback !== "function") { - throw new Error( - "Expected ReactFbErrorUtils.invokeGuardedCallback to be a function." - ); -} + if ( + pendingBoundaries !== null && + !pendingBoundaries.has(offscreenInstance) + ) { + pendingBoundaries.set(offscreenInstance, { + name: name + }); -function invokeGuardedCallbackImpl(name, func, context, a, b, c, d, e, f) { - // This will call `this.onError(err)` if an error was caught. - ReactFbErrorUtils.invokeGuardedCallback.apply(this, arguments); -} + if (transitions !== null) { + if ( + markerInstance.tag === TransitionTracingMarker && + markerName !== null + ) { + addMarkerProgressCallbackToPendingTransition( + markerName, + transitions, + pendingBoundaries + ); + } else if (markerInstance.tag === TransitionRoot) { + transitions.forEach(function (transition) { + addTransitionProgressCallbackToPendingTransition( + transition, + pendingBoundaries + ); + }); + } + } + } + }); + } + } else if (wasHidden && !isHidden) { + // The suspense boundary went from hidden to visible. Remove + // the boundary from the pending suspense boundaries set + // if it's there + if (pendingMarkers !== null) { + pendingMarkers.forEach(function (markerInstance) { + var pendingBoundaries = markerInstance.pendingBoundaries; + var transitions = markerInstance.transitions; + var markerName = markerInstance.name; -var hasError = false; -var caughtError = null; // Used by event system to capture/rethrow the first error. -var reporter = { - onError: function (error) { - hasError = true; - caughtError = error; - } -}; -/** - * Call a function while guarding against errors that happens within it. - * Returns an error if it throws, otherwise null. - * - * In production, this is implemented using a try-catch. The reason we don't - * use a try-catch directly is so that we can swap out a different - * implementation in DEV mode. - * - * @param {String} name of the guard to use for logging or debugging - * @param {Function} func The function to invoke - * @param {*} context The context to use when calling the function - * @param {...*} args Arguments for function - */ + if ( + pendingBoundaries !== null && + pendingBoundaries.has(offscreenInstance) + ) { + pendingBoundaries.delete(offscreenInstance); + + if (transitions !== null) { + if ( + markerInstance.tag === TransitionTracingMarker && + markerName !== null + ) { + addMarkerProgressCallbackToPendingTransition( + markerName, + transitions, + pendingBoundaries + ); // If there are no more unresolved suspense boundaries, the interaction + // is considered finished + + if (pendingBoundaries.size === 0) { + if (markerInstance.aborts === null) { + addMarkerCompleteCallbackToPendingTransition( + markerName, + transitions + ); + } + + markerInstance.transitions = null; + markerInstance.pendingBoundaries = null; + markerInstance.aborts = null; + } + } else if (markerInstance.tag === TransitionRoot) { + transitions.forEach(function (transition) { + addTransitionProgressCallbackToPendingTransition( + transition, + pendingBoundaries + ); + }); + } + } + } + }); + } + } + } + } -function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) { - hasError = false; - caughtError = null; - invokeGuardedCallbackImpl.apply(reporter, arguments); -} -function hasCaughtError() { - return hasError; -} -function clearCaughtError() { - if (hasError) { - var error = caughtError; - hasError = false; - caughtError = null; - return error; - } else { - 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." - ); - } -} + function hideOrUnhideAllChildren(finishedWork, isHidden) { + // Only hide or unhide the top-most host nodes. + var hostSubtreeRoot = null; -var didWarnAboutUndefinedSnapshotBeforeUpdate = null; + { + // We only have the top Fiber that was inserted but we need to recurse down its + // children to find all the terminal nodes. + var node = finishedWork; -{ - didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); -} // Used during the commit phase to track the state of the Offscreen component stack. -// Allows us to avoid traversing the return path to find the nearest Offscreen ancestor. + while (true) { + if (node.tag === HostComponent || false || false) { + if (hostSubtreeRoot === null) { + hostSubtreeRoot = node; -var offscreenSubtreeIsHidden = false; -var offscreenSubtreeWasHidden = false; -var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; -var nextEffect = null; // Used for Profiling builds to track updaters. + try { + var instance = node.stateNode; -var inProgressLanes = null; -var inProgressRoot = null; + if (isHidden) { + hideInstance(instance); + } else { + unhideInstance(node.stateNode, node.memoizedProps); + } + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } + } + } else if (node.tag === HostText) { + if (hostSubtreeRoot === null) { + try { + var _instance = node.stateNode; -function shouldProfile(current) { - return ( - (current.mode & ProfileMode) !== NoMode && - (getExecutionContext() & CommitContext) !== NoContext - ); -} + if (isHidden) { + hideTextInstance(_instance); + } else { + unhideTextInstance(_instance, node.memoizedProps); + } + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } + } + } else if ( + (node.tag === OffscreenComponent || + node.tag === LegacyHiddenComponent) && + node.memoizedState !== null && + node !== finishedWork + ); + else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } -function reportUncaughtErrorInDEV(error) { - // Wrapping each small part of the commit phase into a guarded - // callback is a bit too slow (https://github.com/facebook/react/pull/21666). - // But we rely on it to surface errors to DEV tools like overlays - // (https://github.com/facebook/react/issues/21712). - // As a compromise, rethrow only caught errors in a guard. - { - invokeGuardedCallback(null, function () { - throw error; - }); - clearCaughtError(); - } -} + if (node === finishedWork) { + return; + } -function callComponentWillUnmountWithTimer(current, instance) { - instance.props = current.memoizedProps; - instance.state = current.memoizedState; - - if (shouldProfile(current)) { - try { - startLayoutEffectTimer(); - instance.componentWillUnmount(); - } finally { - recordLayoutEffectDuration(current); - } - } else { - instance.componentWillUnmount(); - } -} // Capture errors so they don't interrupt unmounting. - -function safelyCallComponentWillUnmount( - current, - nearestMountedAncestor, - instance -) { - try { - callComponentWillUnmountWithTimer(current, instance); - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } -} // Capture errors so they don't interrupt mounting. - -function safelyAttachRef(current, nearestMountedAncestor) { - try { - commitAttachRef(current); - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } -} + while (node.sibling === null) { + if (node.return === null || node.return === finishedWork) { + return; + } -function safelyDetachRef(current, nearestMountedAncestor) { - var ref = current.ref; - var refCleanup = current.refCleanup; + if (hostSubtreeRoot === node) { + hostSubtreeRoot = null; + } - if (ref !== null) { - if (typeof refCleanup === "function") { - try { - if (shouldProfile(current)) { - try { - startLayoutEffectTimer(); - refCleanup(); - } finally { - recordLayoutEffectDuration(current); + node = node.return; } - } else { - refCleanup(); - } - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } finally { - // `refCleanup` has been called. Nullify all references to it to prevent double invocation. - current.refCleanup = null; - var finishedWork = current.alternate; - if (finishedWork != null) { - finishedWork.refCleanup = null; - } - } - } else if (typeof ref === "function") { - var retVal; - - try { - if (shouldProfile(current)) { - try { - startLayoutEffectTimer(); - retVal = ref(null); - } finally { - recordLayoutEffectDuration(current); + if (hostSubtreeRoot === node) { + hostSubtreeRoot = null; } - } else { - retVal = ref(null); - } - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } - { - if (typeof retVal === "function") { - error( - "Unexpected return value from a callback ref in %s. " + - "A callback ref should not return a function.", - getComponentNameFromFiber(current) - ); + node.sibling.return = node.return; + node = node.sibling; } } - } else { - // $FlowFixMe[incompatible-use] unable to narrow type to RefObject - ref.current = null; } - } -} -function safelyCallDestroy(current, nearestMountedAncestor, destroy) { - try { - destroy(); - } catch (error) { - captureCommitPhaseError(current, nearestMountedAncestor, error); - } -} + function commitAttachRef(finishedWork) { + var ref = finishedWork.ref; -var focusedInstanceHandle = null; -var shouldFireAfterActiveInstanceBlur = false; -function commitBeforeMutationEffects(root, firstChild) { - focusedInstanceHandle = prepareForCommit(); - nextEffect = firstChild; - commitBeforeMutationEffects_begin(); // We no longer need to track the active instance fiber - - var shouldFire = shouldFireAfterActiveInstanceBlur; - shouldFireAfterActiveInstanceBlur = false; - focusedInstanceHandle = null; - return shouldFire; -} + if (ref !== null) { + var instance = finishedWork.stateNode; + var instanceToUse; -function commitBeforeMutationEffects_begin() { - while (nextEffect !== null) { - var fiber = nextEffect; // This phase is only used for beforeActiveInstanceBlur. - // Let's skip the whole loop if it's off. + switch (finishedWork.tag) { + case HostHoistable: + case HostSingleton: + case HostComponent: + instanceToUse = getPublicInstance(instance); + break; - { - // TODO: Should wrap this in flags check, too, as optimization - var deletions = fiber.deletions; + default: + instanceToUse = instance; + } // Moved outside to ensure DCE works with this flag - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var deletion = deletions[i]; - commitBeforeMutationEffectsDeletion(deletion); + if (finishedWork.tag === ScopeComponent) { + instanceToUse = instance; + } + + if (typeof ref === "function") { + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + finishedWork.refCleanup = ref(instanceToUse); + } finally { + recordLayoutEffectDuration(finishedWork); + } + } else { + finishedWork.refCleanup = ref(instanceToUse); + } + } else { + { + if (!ref.hasOwnProperty("current")) { + error( + "Unexpected ref object provided for %s. " + + "Use either a ref-setter function or React.createRef().", + getComponentNameFromFiber(finishedWork) + ); + } + } // $FlowFixMe[incompatible-use] unable to narrow type to the non-function case + + ref.current = instanceToUse; } } } - var child = fiber.child; + function detachFiberMutation(fiber) { + // Cut off the return pointer to disconnect it from the tree. + // This enables us to detect and warn against state updates on an unmounted component. + // It also prevents events from bubbling from within disconnected components. + // + // Ideally, we should also clear the child pointer of the parent alternate to let this + // get GC:ed but we don't know which for sure which parent is the current + // one so we'll settle for GC:ing the subtree of this child. + // This child itself will be GC:ed when the parent updates the next time. + // + // Note that we can't clear child or sibling pointers yet. + // They're needed for passive effects and for findDOMNode. + // We defer those fields, and all other cleanup, to the passive phase (see detachFiberAfterEffects). + // + // Don't reset the alternate yet, either. We need that so we can detach the + // alternate's fields in the passive phase. Clearing the return pointer is + // sufficient for findDOMNode semantics. + var alternate = fiber.alternate; - if ( - (fiber.subtreeFlags & BeforeMutationMask) !== NoFlags$1 && - child !== null - ) { - child.return = fiber; - nextEffect = child; - } else { - commitBeforeMutationEffects_complete(); + if (alternate !== null) { + alternate.return = null; + } + + fiber.return = null; } - } -} -function commitBeforeMutationEffects_complete() { - while (nextEffect !== null) { - var fiber = nextEffect; - setCurrentFiber(fiber); + function detachFiberAfterEffects(fiber) { + var alternate = fiber.alternate; - try { - commitBeforeMutationEffectsOnFiber(fiber); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } + if (alternate !== null) { + fiber.alternate = null; + detachFiberAfterEffects(alternate); + } // Clear cyclical Fiber fields. This level alone is designed to roughly + // approximate the planned Fiber refactor. In that world, `setState` will be + // bound to a special "instance" object instead of a Fiber. The Instance + // object will not have any of these fields. It will only be connected to + // the fiber tree via a single link at the root. So if this level alone is + // sufficient to fix memory issues, that bodes well for our plans. - resetCurrentFiber(); - var sibling = fiber.sibling; + fiber.child = null; + fiber.deletions = null; + fiber.sibling = null; // The `stateNode` is cyclical because on host nodes it points to the host - if (sibling !== null) { - sibling.return = fiber.return; - nextEffect = sibling; - return; - } + fiber.stateNode = null; - nextEffect = fiber.return; - } -} + { + fiber._debugSource = null; + fiber._debugOwner = null; + } // Theoretically, nothing in here should be necessary, because we already + // disconnected the fiber from the tree. So even if something leaks this + // particular fiber, it won't leak anything else. -function commitBeforeMutationEffectsOnFiber(finishedWork) { - var current = finishedWork.alternate; - var flags = finishedWork.flags; + fiber.return = null; + fiber.dependencies = null; + fiber.memoizedProps = null; + fiber.memoizedState = null; + fiber.pendingProps = null; + fiber.stateNode = null; // TODO: Move to `commitPassiveUnmountInsideDeletedTreeOnFiber` instead. - { - if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) { - // Check to see if the focused element was inside of a hidden (Suspense) subtree. - // TODO: Move this out of the hot path using a dedicated effect tag. - if ( - finishedWork.tag === SuspenseComponent && - isSuspenseBoundaryBeingHidden(current, finishedWork) && // $FlowFixMe[incompatible-call] found when upgrading Flow - doesFiberContain(finishedWork, focusedInstanceHandle) - ) { - shouldFireAfterActiveInstanceBlur = true; - } + fiber.updateQueue = null; } - } - if ((flags & Snapshot) !== NoFlags$1) { - setCurrentFiber(finishedWork); - } + function getHostParentFiber(fiber) { + var parent = fiber.return; - switch (finishedWork.tag) { - case FunctionComponent: { - { - if ((flags & Update) !== NoFlags$1) { - commitUseEffectEventMount(finishedWork); + while (parent !== null) { + if (isHostParent(parent)) { + return parent; } + + parent = parent.return; } - break; + throw new Error( + "Expected to find a host parent. This error is likely caused by a bug " + + "in React. Please file an issue." + ); } - case ForwardRef: - case SimpleMemoComponent: { - break; + function isHostParent(fiber) { + return ( + fiber.tag === HostComponent || + fiber.tag === HostRoot || + false || + false || + fiber.tag === HostPortal + ); } - case ClassComponent: { - if ((flags & Snapshot) !== NoFlags$1) { - if (current !== null) { - var prevProps = current.memoizedProps; - var prevState = current.memoizedState; - var instance = finishedWork.stateNode; // We could update instance props and state here, - // but instead we rely on them being set during last render. - // TODO: revisit this when we implement resuming. + function getHostSibling(fiber) { + // We're going to search forward into the tree until we find a sibling host + // node. Unfortunately, if multiple insertions are done in a row we have to + // search past them. This leads to exponential search for the next sibling. + // TODO: Find a more efficient way to do this. + var node = fiber; - { - if ( - finishedWork.type === finishedWork.elementType && - !didWarnAboutReassigningProps - ) { - if (instance.props !== finishedWork.memoizedProps) { - 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" - ); - } + siblings: while (true) { + // If we didn't find anything, let's try the next sibling. + while (node.sibling === null) { + if (node.return === null || isHostParent(node.return)) { + // If we pop out of the root or hit the parent the fiber we are the + // last sibling. + return null; + } // $FlowFixMe[incompatible-type] found when upgrading Flow - if (instance.state !== finishedWork.memoizedState) { - 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" - ); - } - } + node = node.return; + } + + node.sibling.return = node.return; + node = node.sibling; + + while ( + node.tag !== HostComponent && + node.tag !== HostText && + true && + node.tag !== DehydratedFragment + ) { + // If it is not host node and, we might have a host node inside it. + // Try to search down until we find one. + if (node.flags & Placement) { + // If we don't have a child, try the siblings instead. + continue siblings; + } // If we don't have a child, try the siblings instead. + // We also skip portals because they are not part of this host tree. + + if (node.child === null || node.tag === HostPortal) { + continue siblings; + } else { + node.child.return = node; + node = node.child; } + } // Check if this host node is stable or about to be placed. - var snapshot = instance.getSnapshotBeforeUpdate( - finishedWork.elementType === finishedWork.type - ? prevProps - : resolveDefaultProps(finishedWork.type, prevProps), - prevState - ); + if (!(node.flags & Placement)) { + // Found it! + return node.stateNode; + } + } + } - { - var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate; + function commitPlacement(finishedWork) { + var parentFiber = getHostParentFiber(finishedWork); - if (snapshot === undefined && !didWarnSet.has(finishedWork.type)) { - didWarnSet.add(finishedWork.type); + switch (parentFiber.tag) { + case HostSingleton: - error( - "%s.getSnapshotBeforeUpdate(): A snapshot value (or null) " + - "must be returned. You have returned undefined.", - getComponentNameFromFiber(finishedWork) - ); - } + case HostComponent: { + var _parent = parentFiber.stateNode; + + if (parentFiber.flags & ContentReset) { + parentFiber.flags &= ~ContentReset; } - instance.__reactInternalSnapshotBeforeUpdate = snapshot; + var _before = getHostSibling(finishedWork); // We only have the top Fiber that was inserted but we need to recurse down its + // children to find all the terminal nodes. + + insertOrAppendPlacementNode(finishedWork, _before, _parent); + break; } - } - break; - } + case HostRoot: + case HostPortal: { + var _parent2 = parentFiber.stateNode.containerInfo; - case HostRoot: { - break; - } + var _before2 = getHostSibling(finishedWork); - case HostComponent: - case HostHoistable: - case HostSingleton: - case HostText: - case HostPortal: - case IncompleteClassComponent: - // Nothing to do for these component types - break; + insertOrAppendPlacementNodeIntoContainer( + finishedWork, + _before2, + _parent2 + ); + break; + } - default: { - if ((flags & Snapshot) !== NoFlags$1) { - 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." - ); + default: + throw new Error( + "Invalid host parent fiber. This error is likely caused by a bug " + + "in React. Please file an issue." + ); } } - } - if ((flags & Snapshot) !== NoFlags$1) { - resetCurrentFiber(); - } -} + function insertOrAppendPlacementNodeIntoContainer(node, before, parent) { + var tag = node.tag; + var isHost = tag === HostComponent || tag === HostText; + + if (isHost) { + var stateNode = node.stateNode; + + if (before) { + insertInContainerBefore(parent, stateNode, before); + } else { + appendChildToContainer(parent, stateNode); + } + } else if (tag === HostPortal || false); + else { + var child = node.child; + + if (child !== null) { + insertOrAppendPlacementNodeIntoContainer(child, before, parent); + var sibling = child.sibling; -function commitBeforeMutationEffectsDeletion(deletion) { - { - // TODO (effects) It would be nice to avoid calling doesFiberContain() - // Maybe we can repurpose one of the subtreeFlags positions for this instead? - // Use it to store which part of the tree the focused instance is in? - // This assumes we can safely determine that instance during the "render" phase. - if (doesFiberContain(deletion, focusedInstanceHandle)) { - shouldFireAfterActiveInstanceBlur = true; + while (sibling !== null) { + insertOrAppendPlacementNodeIntoContainer(sibling, before, parent); + sibling = sibling.sibling; + } + } + } } - } -} -function commitHookEffectListUnmount( - flags, - finishedWork, - nearestMountedAncestor -) { - var updateQueue = finishedWork.updateQueue; - var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; + function insertOrAppendPlacementNode(node, before, parent) { + var tag = node.tag; + var isHost = tag === HostComponent || tag === HostText; - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; + if (isHost) { + var stateNode = node.stateNode; - do { - if ((effect.tag & flags) === flags) { - // Unmount - var inst = effect.inst; - var destroy = inst.destroy; + if (before) { + insertBefore(parent, stateNode, before); + } else { + appendChild(parent, stateNode); + } + } else if (tag === HostPortal || false); + else { + var child = node.child; - if (destroy !== undefined) { - inst.destroy = undefined; + if (child !== null) { + insertOrAppendPlacementNode(child, before, parent); + var sibling = child.sibling; - if (enableSchedulingProfiler) { - if ((flags & Passive) !== NoFlags) { - markComponentPassiveEffectUnmountStarted(finishedWork); - } else if ((flags & Layout) !== NoFlags) { - markComponentLayoutEffectUnmountStarted(finishedWork); - } + while (sibling !== null) { + insertOrAppendPlacementNode(sibling, before, parent); + sibling = sibling.sibling; } + } + } + } // These are tracked on the stack as we recursively traverse a + // deleted subtree. + // TODO: Update these during the whole mutation phase, not just during + // a deletion. - { - if ((flags & Insertion) !== NoFlags) { - setIsRunningInsertionEffect(true); - } - } + var hostParent = null; + var hostParentIsContainer = false; - safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy); + function commitDeletionEffects(root, returnFiber, deletedFiber) { + { + // We only have the top Fiber that was deleted but we need to recurse down its + // children to find all the terminal nodes. + // Recursively delete all host nodes from the parent, detach refs, clean + // up mounted layout effects, and call componentWillUnmount. + // We only need to remove the topmost host child in each branch. But then we + // still need to keep traversing to unmount effects, refs, and cWU. TODO: We + // could split this into two separate traversals functions, where the second + // one doesn't include any removeChild logic. This is maybe the same + // function as "disappearLayoutEffects" (or whatever that turns into after + // the layout phase is refactored to use recursion). + // Before starting, find the nearest host parent on the stack so we know + // which instance/container to remove the children from. + // TODO: Instead of searching up the fiber return path on every deletion, we + // can track the nearest host component on the JS stack as we traverse the + // tree during the commit phase. This would make insertions faster, too. + var parent = returnFiber; + + findParent: while (parent !== null) { + switch (parent.tag) { + case HostSingleton: + case HostComponent: { + hostParent = parent.stateNode; + hostParentIsContainer = false; + break findParent; + } - { - if ((flags & Insertion) !== NoFlags) { - setIsRunningInsertionEffect(false); + case HostRoot: { + hostParent = parent.stateNode.containerInfo; + hostParentIsContainer = true; + break findParent; } - } - if (enableSchedulingProfiler) { - if ((flags & Passive) !== NoFlags) { - markComponentPassiveEffectUnmountStopped(); - } else if ((flags & Layout) !== NoFlags) { - markComponentLayoutEffectUnmountStopped(); + case HostPortal: { + hostParent = parent.stateNode.containerInfo; + hostParentIsContainer = true; + break findParent; } } + + parent = parent.return; } - } - effect = effect.next; - } while (effect !== firstEffect); - } -} + if (hostParent === null) { + throw new Error( + "Expected to find a host parent. This error is likely caused by " + + "a bug in React. Please file an issue." + ); + } -function commitHookEffectListMount(flags, finishedWork) { - var updateQueue = finishedWork.updateQueue; - var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; + commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber); + hostParent = null; + hostParentIsContainer = false; + } - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; + detachFiberMutation(deletedFiber); + } - do { - if ((effect.tag & flags) === flags) { - if (enableSchedulingProfiler) { - if ((flags & Passive) !== NoFlags) { - markComponentPassiveEffectMountStarted(finishedWork); - } else if ((flags & Layout) !== NoFlags) { - markComponentLayoutEffectMountStarted(finishedWork); - } - } // Mount + function recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + parent + ) { + // TODO: Use a static flag to skip trees that don't have unmount effects + var child = parent.child; - var create = effect.create; + while (child !== null) { + commitDeletionEffectsOnFiber( + finishedRoot, + nearestMountedAncestor, + child + ); + child = child.sibling; + } + } - { - if ((flags & Insertion) !== NoFlags) { - setIsRunningInsertionEffect(true); - } - } + function commitDeletionEffectsOnFiber( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ) { + onCommitUnmount(deletedFiber); // The cases in this outer switch modify the stack before they traverse + // into their subtree. There are simpler cases in the inner switch + // that don't modify the stack. - var inst = effect.inst; - var destroy = create(); - inst.destroy = destroy; + switch (deletedFiber.tag) { + case HostHoistable: - { - if ((flags & Insertion) !== NoFlags) { - setIsRunningInsertionEffect(false); - } + case HostSingleton: + + case HostComponent: { + if (!offscreenSubtreeWasHidden) { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + } // Intentional fallthrough to next branch } - if (enableSchedulingProfiler) { - if ((flags & Passive) !== NoFlags) { - markComponentPassiveEffectMountStopped(); - } else if ((flags & Layout) !== NoFlags) { - markComponentLayoutEffectMountStopped(); + case HostText: { + // We only need to remove the nearest host child. Set the host parent + // to `null` on the stack to indicate that nested children don't + // need to be removed. + { + var _prevHostParent = hostParent; + var _prevHostParentIsContainer = hostParentIsContainer; + hostParent = null; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + hostParent = _prevHostParent; + hostParentIsContainer = _prevHostParentIsContainer; + + if (hostParent !== null) { + // Now that all the child effects have unmounted, we can remove the + // node from the tree. + if (hostParentIsContainer) { + removeChildFromContainer(hostParent, deletedFiber.stateNode); + } else { + removeChild(hostParent, deletedFiber.stateNode); + } + } } + + return; } - { - if (destroy !== undefined && typeof destroy !== "function") { - var hookName = void 0; + case DehydratedFragment: { + { + var hydrationCallbacks = finishedRoot.hydrationCallbacks; - if ((effect.tag & Layout) !== NoFlags$1) { - hookName = "useLayoutEffect"; - } else if ((effect.tag & Insertion) !== NoFlags$1) { - hookName = "useInsertionEffect"; - } else { - hookName = "useEffect"; - } + if (hydrationCallbacks !== null) { + var onDeleted = hydrationCallbacks.onDeleted; - var addendum = void 0; + if (onDeleted) { + onDeleted(deletedFiber.stateNode); + } + } + } // Dehydrated fragments don't have any children + // Delete the dehydrated suspense boundary and all of its content. - if (destroy === null) { - addendum = - " You returned null. If your effect does not require clean " + - "up, return undefined (or nothing)."; - } else if (typeof destroy.then === "function") { - 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"; - } else { - addendum = " You returned: " + destroy; + { + if (hostParent !== null) { + if (hostParentIsContainer) { + clearSuspenseBoundaryFromContainer(); + } else { + clearSuspenseBoundary(); + } } + } - error( - "%s must not return anything besides a function, " + - "which is used for clean-up.%s", - hookName, - addendum + return; + } + + case HostPortal: { + { + // When we go into a portal, it becomes the parent to remove from. + var _prevHostParent2 = hostParent; + var _prevHostParentIsContainer2 = hostParentIsContainer; + hostParent = deletedFiber.stateNode.containerInfo; + hostParentIsContainer = true; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber ); + hostParent = _prevHostParent2; + hostParentIsContainer = _prevHostParentIsContainer2; } - } - } - effect = effect.next; - } while (effect !== firstEffect); - } -} + return; + } -function commitUseEffectEventMount(finishedWork) { - var updateQueue = finishedWork.updateQueue; - var eventPayloads = updateQueue !== null ? updateQueue.events : null; + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + if (!offscreenSubtreeWasHidden) { + var updateQueue = deletedFiber.updateQueue; + + if (updateQueue !== null) { + var lastEffect = updateQueue.lastEffect; + + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; + + do { + var tag = effect.tag; + var inst = effect.inst; + var destroy = inst.destroy; + + if (destroy !== undefined) { + if ((tag & Insertion) !== NoFlags) { + inst.destroy = undefined; + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + } else if ((tag & Layout) !== NoFlags) { + if (enableSchedulingProfiler) { + markComponentLayoutEffectUnmountStarted(deletedFiber); + } + + if (shouldProfile(deletedFiber)) { + startLayoutEffectTimer(); + inst.destroy = undefined; + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + recordLayoutEffectDuration(deletedFiber); + } else { + inst.destroy = undefined; + safelyCallDestroy( + deletedFiber, + nearestMountedAncestor, + destroy + ); + } + + if (enableSchedulingProfiler) { + markComponentLayoutEffectUnmountStopped(); + } + } + } - if (eventPayloads !== null) { - for (var ii = 0; ii < eventPayloads.length; ii++) { - var _eventPayloads$ii = eventPayloads[ii], - ref = _eventPayloads$ii.ref, - nextImpl = _eventPayloads$ii.nextImpl; - ref.impl = nextImpl; - } - } -} + effect = effect.next; + } while (effect !== firstEffect); + } + } + } -function commitPassiveEffectDurations(finishedRoot, finishedWork) { - if (getExecutionContext() & CommitContext) { - // Only Profilers with work in their subtree will have an Update effect scheduled. - if ((finishedWork.flags & Update) !== NoFlags$1) { - switch (finishedWork.tag) { - case Profiler: { - var passiveEffectDuration = - finishedWork.stateNode.passiveEffectDuration; - var _finishedWork$memoize = finishedWork.memoizedProps, - id = _finishedWork$memoize.id, - onPostCommit = _finishedWork$memoize.onPostCommit; // This value will still reflect the previous commit phase. - // It does not get reset until the start of the next commit phase. + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; + } - var commitTime = getCommitTime(); - var phase = finishedWork.alternate === null ? "mount" : "update"; + case ClassComponent: { + if (!offscreenSubtreeWasHidden) { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + var instance = deletedFiber.stateNode; - { - if (isCurrentUpdateNested()) { - phase = "nested-update"; + if (typeof instance.componentWillUnmount === "function") { + safelyCallComponentWillUnmount( + deletedFiber, + nearestMountedAncestor, + instance + ); } } - if (typeof onPostCommit === "function") { - onPostCommit(id, phase, passiveEffectDuration, commitTime); - } // Bubble times to the next nearest ancestor Profiler. - // After we process that Profiler, we'll bubble further up. - - var parentFiber = finishedWork.return; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; + } - outer: while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; - root.passiveEffectDuration += passiveEffectDuration; - break outer; + case ScopeComponent: { + { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + } - case Profiler: - var parentStateNode = parentFiber.stateNode; - parentStateNode.passiveEffectDuration += passiveEffectDuration; - break outer; - } + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + return; + } - parentFiber = parentFiber.return; + case OffscreenComponent: { + safelyDetachRef(deletedFiber, nearestMountedAncestor); + + if (deletedFiber.mode & ConcurrentMode) { + // If this offscreen component is hidden, we already unmounted it. Before + // deleting the children, track that it's already unmounted so that we + // don't attempt to unmount the effects again. + // TODO: If the tree is hidden, in most cases we should be able to skip + // over the nested children entirely. An exception is we haven't yet found + // the topmost host node to delete, which we already track on the stack. + // But the other case is portals, which need to be detached no matter how + // deeply they are nested. We should use a subtree flag to track whether a + // subtree includes a nested portal. + var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; + offscreenSubtreeWasHidden = + prevOffscreenSubtreeWasHidden || + deletedFiber.memoizedState !== null; + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); + offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; + } else { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber + ); } break; } - } - } - } -} - -function commitHookLayoutEffects(finishedWork, hookFlags) { - // At this point layout effects have already been destroyed (during mutation phase). - // This is done to prevent sibling component effects from interfering with each other, - // e.g. a destroy function in one component should never override a ref set - // by a create function in another component during the same commit. - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - commitHookEffectListMount(hookFlags, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - - recordLayoutEffectDuration(finishedWork); - } else { - try { - commitHookEffectListMount(hookFlags, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - } -} - -function commitClassLayoutLifecycles(finishedWork, current) { - var instance = finishedWork.stateNode; - - if (current === null) { - // We could update instance props and state here, - // but instead we rely on them being set during last render. - // TODO: revisit this when we implement resuming. - { - if ( - finishedWork.type === finishedWork.elementType && - !didWarnAboutReassigningProps - ) { - if (instance.props !== finishedWork.memoizedProps) { - 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" - ); - } - if (instance.state !== finishedWork.memoizedState) { - 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" + default: { + recursivelyTraverseDeletionEffects( + finishedRoot, + nearestMountedAncestor, + deletedFiber ); + return; } } } - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - instance.componentDidMount(); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + function commitSuspenseCallback(finishedWork) { + // TODO: Move this to passive phase + var newState = finishedWork.memoizedState; - recordLayoutEffectDuration(finishedWork); - } else { - try { - instance.componentDidMount(); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - } - } else { - var prevProps = - finishedWork.elementType === finishedWork.type - ? current.memoizedProps - : resolveDefaultProps(finishedWork.type, current.memoizedProps); - var prevState = current.memoizedState; // We could update instance props and state here, - // but instead we rely on them being set during last render. - // TODO: revisit this when we implement resuming. + if (newState !== null) { + var suspenseCallback = finishedWork.memoizedProps.suspenseCallback; - { - if ( - finishedWork.type === finishedWork.elementType && - !didWarnAboutReassigningProps - ) { - if (instance.props !== finishedWork.memoizedProps) { - 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" - ); - } + if (typeof suspenseCallback === "function") { + var retryQueue = finishedWork.updateQueue; - if (instance.state !== finishedWork.memoizedState) { - 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" - ); + if (retryQueue !== null) { + suspenseCallback(new Set(retryQueue)); + } + } else { + if (suspenseCallback !== undefined) { + error("Unexpected type for suspenseCallback."); + } } } } - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - instance.componentDidUpdate( - prevProps, - prevState, - instance.__reactInternalSnapshotBeforeUpdate - ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + function getRetryCache(finishedWork) { + // TODO: Unify the interface for the retry cache so we don't have to switch + // on the tag like this. + switch (finishedWork.tag) { + case SuspenseComponent: + case SuspenseListComponent: { + var retryCache = finishedWork.stateNode; - recordLayoutEffectDuration(finishedWork); - } else { - try { - instance.componentDidUpdate( - prevProps, - prevState, - instance.__reactInternalSnapshotBeforeUpdate - ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - } - } -} + if (retryCache === null) { + retryCache = finishedWork.stateNode = new PossiblyWeakSet(); + } -function commitClassCallbacks(finishedWork) { - // TODO: I think this is now always non-null by the time it reaches the - // commit phase. Consider removing the type check. - var updateQueue = finishedWork.updateQueue; + return retryCache; + } - if (updateQueue !== null) { - var instance = finishedWork.stateNode; + case OffscreenComponent: { + var instance = finishedWork.stateNode; + var _retryCache = instance._retryCache; - { - if ( - finishedWork.type === finishedWork.elementType && - !didWarnAboutReassigningProps - ) { - if (instance.props !== finishedWork.memoizedProps) { - 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" - ); + if (_retryCache === null) { + _retryCache = instance._retryCache = new PossiblyWeakSet(); + } + + return _retryCache; } - if (instance.state !== finishedWork.memoizedState) { - 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" + default: { + throw new Error( + "Unexpected Suspense handler tag (" + + finishedWork.tag + + "). This is a " + + "bug in React." ); } } - } // We could update instance props and state here, - // but instead we rely on them being set during last render. - // TODO: revisit this when we implement resuming. - - try { - commitCallbacks(updateQueue, instance); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); } - } -} -function commitHostComponentMount(finishedWork) { - var type = finishedWork.type; - var props = finishedWork.memoizedProps; - var instance = finishedWork.stateNode; + function detachOffscreenInstance(instance) { + var fiber = instance._current; - try { - commitMount(instance, type, props, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } -} - -function commitProfilerUpdate(finishedWork, current) { - if (getExecutionContext() & CommitContext) { - try { - var _finishedWork$memoize2 = finishedWork.memoizedProps, - onCommit = _finishedWork$memoize2.onCommit, - onRender = _finishedWork$memoize2.onRender; - var effectDuration = finishedWork.stateNode.effectDuration; - var commitTime = getCommitTime(); - var phase = current === null ? "mount" : "update"; - - if (enableProfilerNestedUpdatePhase) { - if (isCurrentUpdateNested()) { - phase = "nested-update"; - } - } - - if (typeof onRender === "function") { - onRender( - finishedWork.memoizedProps.id, - phase, - finishedWork.actualDuration, - finishedWork.treeBaseDuration, - finishedWork.actualStartTime, - commitTime + if (fiber === null) { + throw new Error( + "Calling Offscreen.detach before instance handle has been set." ); } - if (enableProfilerCommitHooks) { - if (typeof onCommit === "function") { - onCommit( - finishedWork.memoizedProps.id, - phase, - effectDuration, - commitTime - ); - } // Schedule a passive effect for this Profiler to call onPostCommit hooks. - // This effect should be scheduled even if there is no onPostCommit callback for this Profiler, - // because the effect is also where times bubble to parent Profilers. - - enqueuePendingPassiveProfilerEffect(finishedWork); // Propagate layout effect durations to the next nearest Profiler ancestor. - // Do not reset these values until the next render so DevTools has a chance to read them first. - - var parentFiber = finishedWork.return; - - outer: while (parentFiber !== null) { - switch (parentFiber.tag) { - case HostRoot: - var root = parentFiber.stateNode; - root.effectDuration += effectDuration; - break outer; + if ((instance._pendingVisibility & OffscreenDetached) !== NoFlags$1) { + // The instance is already detached, this is a noop. + return; + } // TODO: There is an opportunity to optimise this by not entering commit phase + // and unmounting effects directly. - case Profiler: - var parentStateNode = parentFiber.stateNode; - parentStateNode.effectDuration += effectDuration; - break outer; - } + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - parentFiber = parentFiber.return; - } + if (root !== null) { + instance._pendingVisibility |= OffscreenDetached; + scheduleUpdateOnFiber(root, fiber, SyncLane); } - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); } - } -} + function attachOffscreenInstance(instance) { + var fiber = instance._current; -function commitLayoutEffectOnFiber( - finishedRoot, - current, - finishedWork, - committedLanes -) { - // When updating this function, also update reappearLayoutEffects, which does - // most of the same things when an offscreen tree goes from hidden -> visible. - var flags = finishedWork.flags; - - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - - if (flags & Update) { - commitHookLayoutEffects(finishedWork, Layout | HasEffect); + if (fiber === null) { + throw new Error( + "Calling Offscreen.detach before instance handle has been set." + ); } - break; - } - - case ClassComponent: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - - if (flags & Update) { - commitClassLayoutLifecycles(finishedWork, current); + if ((instance._pendingVisibility & OffscreenDetached) === NoFlags$1) { + // The instance is already attached, this is a noop. + return; } - if (flags & Callback) { - commitClassCallbacks(finishedWork); - } + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (flags & Ref) { - safelyAttachRef(finishedWork, finishedWork.return); + if (root !== null) { + instance._pendingVisibility &= ~OffscreenDetached; + scheduleUpdateOnFiber(root, fiber, SyncLane); } - - break; } - case HostRoot: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - - if (flags & Callback) { - // TODO: I think this is now always non-null by the time it reaches the - // commit phase. Consider removing the type check. - var updateQueue = finishedWork.updateQueue; + function attachSuspenseRetryListeners(finishedWork, wakeables) { + // If this boundary just timed out, then it will have a set of wakeables. + // For each wakeable, attach a listener so that when it resolves, React + // attempts to re-render the boundary in the primary (pre-timeout) state. + var retryCache = getRetryCache(finishedWork); + wakeables.forEach(function (wakeable) { + // Memoize using the boundary fiber to prevent redundant listeners. + var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); - if (updateQueue !== null) { - var instance = null; - - if (finishedWork.child !== null) { - switch (finishedWork.child.tag) { - case HostSingleton: - case HostComponent: - instance = getPublicInstance(finishedWork.child.stateNode); - break; + if (!retryCache.has(wakeable)) { + retryCache.add(wakeable); - case ClassComponent: - instance = finishedWork.child.stateNode; - break; + { + if (isDevToolsPresent) { + if (inProgressLanes !== null && inProgressRoot !== null) { + // If we have pending work still, associate the original updaters with it. + restorePendingUpdaters(inProgressRoot, inProgressLanes); + } else { + throw Error( + "Expected finished root and lanes to be set. This is a bug in React." + ); + } } } - try { - commitCallbacks(updateQueue, instance); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + wakeable.then(retry, retry); } - } - - break; - } - - case HostHoistable: - - case HostSingleton: - case HostComponent: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); // Renderers may schedule work to be done after host components are mounted - // (eg DOM renderer may schedule auto-focus for inputs and form controls). - // These effects should only be committed when components are first mounted, - // aka when there is no current/alternate. - - if (current === null && flags & Update) { - commitHostComponentMount(finishedWork); - } - - if (flags & Ref) { - safelyAttachRef(finishedWork, finishedWork.return); - } - - break; - } + }); + } // This function detects when a Suspense boundary goes from visible to hidden. + // It returns false if the boundary is already hidden. + // TODO: Use an effect tag. - case Profiler: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); // TODO: Should this fire inside an offscreen tree? Or should it wait to - // fire when the tree becomes visible again. + function isSuspenseBoundaryBeingHidden(current, finishedWork) { + if (current !== null) { + var oldState = current.memoizedState; - if (flags & Update) { - commitProfilerUpdate(finishedWork, current); + if (oldState === null || oldState.dehydrated !== null) { + var newState = finishedWork.memoizedState; + return newState !== null && newState.dehydrated === null; + } } - break; + return false; } - - case SuspenseComponent: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - - break; + function commitMutationEffects(root, finishedWork, committedLanes) { + inProgressLanes = committedLanes; + inProgressRoot = root; + setCurrentFiber(finishedWork); + commitMutationEffectsOnFiber(finishedWork, root); + setCurrentFiber(finishedWork); + inProgressLanes = null; + inProgressRoot = null; } - case OffscreenComponent: { - var isModernRoot = (finishedWork.mode & ConcurrentMode) !== NoMode; + function recursivelyTraverseMutationEffects(root, parentFiber, lanes) { + // Deletions effects can be scheduled on any fiber type. They need to happen + // before the children effects hae fired. + var deletions = parentFiber.deletions; - if (isModernRoot) { - var isHidden = finishedWork.memoizedState !== null; - var newOffscreenSubtreeIsHidden = isHidden || offscreenSubtreeIsHidden; + if (deletions !== null) { + for (var i = 0; i < deletions.length; i++) { + var childToDelete = deletions[i]; - if (newOffscreenSubtreeIsHidden); - else { - // The Offscreen tree is visible. - var wasHidden = current !== null && current.memoizedState !== null; - var newOffscreenSubtreeWasHidden = - wasHidden || offscreenSubtreeWasHidden; - var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden; - var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; - offscreenSubtreeIsHidden = newOffscreenSubtreeIsHidden; - offscreenSubtreeWasHidden = newOffscreenSubtreeWasHidden; - - if (offscreenSubtreeWasHidden && !prevOffscreenSubtreeWasHidden) { - // This is the root of a reappearing boundary. As we continue - // traversing the layout effects, we must also re-mount layout - // effects that were unmounted when the Offscreen subtree was - // hidden. So this is a superset of the normal commitLayoutEffects. - var includeWorkInProgressEffects = - (finishedWork.subtreeFlags & LayoutMask) !== NoFlags$1; - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); - } else { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + try { + commitDeletionEffects(root, parentFiber, childToDelete); + } catch (error) { + captureCommitPhaseError(childToDelete, parentFiber, error); } - - offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; - offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; } - } else { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); } - if (flags & Ref) { - var props = finishedWork.memoizedProps; + var prevDebugFiber = getCurrentFiber(); - if (props.mode === "manual") { - safelyAttachRef(finishedWork, finishedWork.return); - } else { - safelyDetachRef(finishedWork, finishedWork.return); + if (parentFiber.subtreeFlags & MutationMask) { + var child = parentFiber.child; + + while (child !== null) { + setCurrentFiber(child); + commitMutationEffectsOnFiber(child, root); + child = child.sibling; } } - break; - } - - default: { - recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); - break; + setCurrentFiber(prevDebugFiber); } - } -} -function abortRootTransitions( - root, - abort, - deletedTransitions, - deletedOffscreenInstance, - isInDeletedTree -) { - if (enableTransitionTracing) { - var rootTransitions = root.incompleteTransitions; - deletedTransitions.forEach(function (transition) { - if (rootTransitions.has(transition)) { - var transitionInstance = rootTransitions.get(transition); + function commitMutationEffectsOnFiber(finishedWork, root, lanes) { + var current = finishedWork.alternate; + var flags = finishedWork.flags; // The effect flag should be checked *after* we refine the type of fiber, + // because the fiber tag is more specific. An exception is any flag related + // to reconciliation, because those can be set on all fiber types. - if (transitionInstance.aborts === null) { - transitionInstance.aborts = []; - } + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - transitionInstance.aborts.push(abort); + if (flags & Update) { + try { + commitHookEffectListUnmount( + Insertion | HasEffect, + finishedWork, + finishedWork.return + ); + commitHookEffectListMount(Insertion | HasEffect, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } // Layout effects are destroyed during the mutation phase so that all + // destroy functions for all fibers are called before any create functions. + // This prevents sibling component effects from interfering with each other, + // e.g. a destroy function in one component should never override a ref set + // by a create function in another component during the same commit. + + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + commitHookEffectListUnmount( + Layout | HasEffect, + finishedWork, + finishedWork.return + ); + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } - if (deletedOffscreenInstance !== null) { - if ( - transitionInstance.pendingBoundaries !== null && - transitionInstance.pendingBoundaries.has(deletedOffscreenInstance) - ) { - // $FlowFixMe[incompatible-use] found when upgrading Flow - transitionInstance.pendingBoundaries.delete( - deletedOffscreenInstance - ); + recordLayoutEffectDuration(finishedWork); + } else { + try { + commitHookEffectListUnmount( + Layout | HasEffect, + finishedWork, + finishedWork.return + ); + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } + } } + + return; } - } - }); - } -} -function abortTracingMarkerTransitions( - abortedFiber, - abort, - deletedTransitions, - deletedOffscreenInstance, - isInDeletedTree -) { - if (enableTransitionTracing) { - var markerInstance = abortedFiber.stateNode; - var markerTransitions = markerInstance.transitions; - var pendingBoundaries = markerInstance.pendingBoundaries; - - if (markerTransitions !== null) { - // TODO: Refactor this code. Is there a way to move this code to - // the deletions phase instead of calculating it here while making sure - // complete is called appropriately? - deletedTransitions.forEach(function (transition) { - // If one of the transitions on the tracing marker is a transition - // that was in an aborted subtree, we will abort that tracing marker - if ( - abortedFiber !== null && - markerTransitions.has(transition) && - (markerInstance.aborts === null || - !markerInstance.aborts.includes(abort)) - ) { - if (markerInstance.transitions !== null) { - if (markerInstance.aborts === null) { - markerInstance.aborts = [abort]; - addMarkerIncompleteCallbackToPendingTransition( - abortedFiber.memoizedProps.name, - markerInstance.transitions, - markerInstance.aborts - ); - } else { - markerInstance.aborts.push(abort); - } // We only want to call onTransitionProgress when the marker hasn't been - // deleted + case ClassComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - if ( - deletedOffscreenInstance !== null && - !isInDeletedTree && - pendingBoundaries !== null && - pendingBoundaries.has(deletedOffscreenInstance) - ) { - pendingBoundaries.delete(deletedOffscreenInstance); - addMarkerProgressCallbackToPendingTransition( - abortedFiber.memoizedProps.name, - deletedTransitions, - pendingBoundaries - ); + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(current, current.return); } } - } - }); - } - } -} -function abortParentMarkerTransitionsForDeletedFiber( - abortedFiber, - abort, - deletedTransitions, - deletedOffscreenInstance, - isInDeletedTree -) { - if (enableTransitionTracing) { - // Find all pending markers that are waiting on child suspense boundaries in the - // aborted subtree and cancels them - var fiber = abortedFiber; - - while (fiber !== null) { - switch (fiber.tag) { - case TracingMarkerComponent: - abortTracingMarkerTransitions( - fiber, - abort, - deletedTransitions, - deletedOffscreenInstance, - isInDeletedTree - ); - break; + if (flags & Callback && offscreenSubtreeIsHidden) { + var updateQueue = finishedWork.updateQueue; - case HostRoot: - var root = fiber.stateNode; - abortRootTransitions( - root, - abort, - deletedTransitions, - deletedOffscreenInstance - ); - break; - } + if (updateQueue !== null) { + deferHiddenCallbacks(updateQueue); + } + } - fiber = fiber.return; - } - } -} + return; + } -function commitTransitionProgress(offscreenFiber) { - if (enableTransitionTracing) { - // This function adds suspense boundaries to the root - // or tracing marker's pendingBoundaries map. - // When a suspense boundary goes from a resolved to a fallback - // state we add the boundary to the map, and when it goes from - // a fallback to a resolved state, we remove the boundary from - // the map. - // We use stateNode on the Offscreen component as a stable object - // that doesnt change from render to render. This way we can - // distinguish between different Offscreen instances (vs. the same - // Offscreen instance with different fibers) - var offscreenInstance = offscreenFiber.stateNode; - var prevState = null; - var previousFiber = offscreenFiber.alternate; - - if (previousFiber !== null && previousFiber.memoizedState !== null) { - prevState = previousFiber.memoizedState; - } - - var nextState = offscreenFiber.memoizedState; - var wasHidden = prevState !== null; - var isHidden = nextState !== null; - var pendingMarkers = offscreenInstance._pendingMarkers; // If there is a name on the suspense boundary, store that in - // the pending boundaries. - - var name = null; - var parent = offscreenFiber.return; + case HostHoistable: - if ( - parent !== null && - parent.tag === SuspenseComponent && - parent.memoizedProps.unstable_name - ) { - name = parent.memoizedProps.unstable_name; - } + case HostSingleton: - if (!wasHidden && isHidden) { - // The suspense boundaries was just hidden. Add the boundary - // to the pending boundary set if it's there - if (pendingMarkers !== null) { - pendingMarkers.forEach(function (markerInstance) { - var pendingBoundaries = markerInstance.pendingBoundaries; - var transitions = markerInstance.transitions; - var markerName = markerInstance.name; + case HostComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - if ( - pendingBoundaries !== null && - !pendingBoundaries.has(offscreenInstance) - ) { - pendingBoundaries.set(offscreenInstance, { - name: name - }); + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(current, current.return); + } + } - if (transitions !== null) { - if ( - markerInstance.tag === TransitionTracingMarker && - markerName !== null - ) { - addMarkerProgressCallbackToPendingTransition( - markerName, - transitions, - pendingBoundaries + { + // TODO: ContentReset gets cleared by the children during the commit + // phase. This is a refactor hazard because it means we must read + // flags the flags after `commitReconciliationEffects` has already run; + // the order matters. We should refactor so that ContentReset does not + // rely on mutating the flag during commit. Like by setting a flag + // during the render phase instead. + if (finishedWork.flags & ContentReset) { + var instance = finishedWork.stateNode; + + try { + resetTextContent(instance); + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error ); - } else if (markerInstance.tag === TransitionRoot) { - transitions.forEach(function (transition) { - addTransitionProgressCallbackToPendingTransition( - transition, - pendingBoundaries - ); - }); } } - } - }); - } - } else if (wasHidden && !isHidden) { - // The suspense boundary went from hidden to visible. Remove - // the boundary from the pending suspense boundaries set - // if it's there - if (pendingMarkers !== null) { - pendingMarkers.forEach(function (markerInstance) { - var pendingBoundaries = markerInstance.pendingBoundaries; - var transitions = markerInstance.transitions; - var markerName = markerInstance.name; - - if ( - pendingBoundaries !== null && - pendingBoundaries.has(offscreenInstance) - ) { - pendingBoundaries.delete(offscreenInstance); - - if (transitions !== null) { - if ( - markerInstance.tag === TransitionTracingMarker && - markerName !== null - ) { - addMarkerProgressCallbackToPendingTransition( - markerName, - transitions, - pendingBoundaries - ); // If there are no more unresolved suspense boundaries, the interaction - // is considered finished - - if (pendingBoundaries.size === 0) { - if (markerInstance.aborts === null) { - addMarkerCompleteCallbackToPendingTransition( - markerName, - transitions - ); - } - markerInstance.transitions = null; - markerInstance.pendingBoundaries = null; - markerInstance.aborts = null; - } - } else if (markerInstance.tag === TransitionRoot) { - transitions.forEach(function (transition) { - addTransitionProgressCallbackToPendingTransition( - transition, - pendingBoundaries + if (flags & Update) { + var _instance2 = finishedWork.stateNode; + + if (_instance2 != null) { + // Commit the work prepared earlier. + var newProps = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps + // as the newProps. The updatePayload will contain the real change in + // this case. + + var oldProps = + current !== null ? current.memoizedProps : newProps; + var type = finishedWork.type; // TODO: Type the updateQueue to be specific to host components. + + var _updatePayload = finishedWork.updateQueue; + finishedWork.updateQueue = null; + + try { + commitUpdate( + _instance2, + _updatePayload, + type, + oldProps, + newProps, + finishedWork ); - }); + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } } } - } - }); - } - } - } -} + } -function hideOrUnhideAllChildren(finishedWork, isHidden) { - // Only hide or unhide the top-most host nodes. - var hostSubtreeRoot = null; + return; + } - { - // We only have the top Fiber that was inserted but we need to recurse down its - // children to find all the terminal nodes. - var node = finishedWork; + case HostText: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - while (true) { - if (node.tag === HostComponent || false || false) { - if (hostSubtreeRoot === null) { - hostSubtreeRoot = node; + if (flags & Update) { + { + if (finishedWork.stateNode === null) { + throw new Error( + "This should have a text node initialized. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + } - try { - var instance = node.stateNode; + var textInstance = finishedWork.stateNode; + var newText = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps + // as the newProps. The updatePayload will contain the real change in + // this case. - if (isHidden) { - hideInstance(instance); - } else { - unhideInstance(node.stateNode, node.memoizedProps); - } - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - } - } else if (node.tag === HostText) { - if (hostSubtreeRoot === null) { - try { - var _instance = node.stateNode; + var oldText = current !== null ? current.memoizedProps : newText; - if (isHidden) { - hideTextInstance(_instance); - } else { - unhideTextInstance(_instance, node.memoizedProps); + try { + commitTextUpdate(textInstance, oldText, newText); + } catch (error) { + captureCommitPhaseError( + finishedWork, + finishedWork.return, + error + ); + } } - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); } + + return; } - } else if ( - (node.tag === OffscreenComponent || - node.tag === LegacyHiddenComponent) && - node.memoizedState !== null && - node !== finishedWork - ); - else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } - if (node === finishedWork) { - return; - } + case HostRoot: { + { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + } - while (node.sibling === null) { - if (node.return === null || node.return === finishedWork) { return; } - if (hostSubtreeRoot === node) { - hostSubtreeRoot = null; - } + case HostPortal: { + { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + } - node = node.return; - } + return; + } - if (hostSubtreeRoot === node) { - hostSubtreeRoot = null; - } + case SuspenseComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); // TODO: We should mark a flag on the Suspense fiber itself, rather than + // relying on the Offscreen fiber having a flag also being marked. The + // reason is that this offscreen fiber might not be part of the work-in- + // progress tree! It could have been reused from a previous render. This + // doesn't lead to incorrect behavior because we don't rely on the flag + // check alone; we also compare the states explicitly below. But for + // modeling purposes, we _should_ be able to rely on the flag check alone. + // So this is a bit fragile. + // + // Also, all this logic could/should move to the passive phase so it + // doesn't block paint. - node.sibling.return = node.return; - node = node.sibling; - } - } -} + var offscreenFiber = finishedWork.child; -function commitAttachRef(finishedWork) { - var ref = finishedWork.ref; + if (offscreenFiber.flags & Visibility) { + // Throttle the appearance and disappearance of Suspense fallbacks. + var isShowingFallback = finishedWork.memoizedState !== null; + var wasShowingFallback = + current !== null && current.memoizedState !== null; - if (ref !== null) { - var instance = finishedWork.stateNode; - var instanceToUse; + if (alwaysThrottleRetries) { + if (isShowingFallback !== wasShowingFallback) { + // A fallback is either appearing or disappearing. + markCommitTimeOfFallback(); + } + } else { + if (isShowingFallback && !wasShowingFallback) { + // Old behavior. Only mark when a fallback appears, not when + // it disappears. + markCommitTimeOfFallback(); + } + } + } - switch (finishedWork.tag) { - case HostHoistable: - case HostSingleton: - case HostComponent: - instanceToUse = getPublicInstance(instance); - break; + if (flags & Update) { + try { + commitSuspenseCallback(finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } - default: - instanceToUse = instance; - } // Moved outside to ensure DCE works with this flag + var retryQueue = finishedWork.updateQueue; - if (finishedWork.tag === ScopeComponent) { - instanceToUse = instance; - } + if (retryQueue !== null) { + finishedWork.updateQueue = null; + attachSuspenseRetryListeners(finishedWork, retryQueue); + } + } - if (typeof ref === "function") { - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - finishedWork.refCleanup = ref(instanceToUse); - } finally { - recordLayoutEffectDuration(finishedWork); - } - } else { - finishedWork.refCleanup = ref(instanceToUse); - } - } else { - { - if (!ref.hasOwnProperty("current")) { - error( - "Unexpected ref object provided for %s. " + - "Use either a ref-setter function or React.createRef().", - getComponentNameFromFiber(finishedWork) - ); + return; } - } // $FlowFixMe[incompatible-use] unable to narrow type to the non-function case - ref.current = instanceToUse; - } - } -} - -function detachFiberMutation(fiber) { - // Cut off the return pointer to disconnect it from the tree. - // This enables us to detect and warn against state updates on an unmounted component. - // It also prevents events from bubbling from within disconnected components. - // - // Ideally, we should also clear the child pointer of the parent alternate to let this - // get GC:ed but we don't know which for sure which parent is the current - // one so we'll settle for GC:ing the subtree of this child. - // This child itself will be GC:ed when the parent updates the next time. - // - // Note that we can't clear child or sibling pointers yet. - // They're needed for passive effects and for findDOMNode. - // We defer those fields, and all other cleanup, to the passive phase (see detachFiberAfterEffects). - // - // Don't reset the alternate yet, either. We need that so we can detach the - // alternate's fields in the passive phase. Clearing the return pointer is - // sufficient for findDOMNode semantics. - var alternate = fiber.alternate; - - if (alternate !== null) { - alternate.return = null; - } - - fiber.return = null; -} + case OffscreenComponent: { + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(current, current.return); + } + } -function detachFiberAfterEffects(fiber) { - var alternate = fiber.alternate; - - if (alternate !== null) { - fiber.alternate = null; - detachFiberAfterEffects(alternate); - } // Clear cyclical Fiber fields. This level alone is designed to roughly - // approximate the planned Fiber refactor. In that world, `setState` will be - // bound to a special "instance" object instead of a Fiber. The Instance - // object will not have any of these fields. It will only be connected to - // the fiber tree via a single link at the root. So if this level alone is - // sufficient to fix memory issues, that bodes well for our plans. - - fiber.child = null; - fiber.deletions = null; - fiber.sibling = null; // The `stateNode` is cyclical because on host nodes it points to the host - - fiber.stateNode = null; - - { - fiber._debugSource = null; - fiber._debugOwner = null; - } // Theoretically, nothing in here should be necessary, because we already - // disconnected the fiber from the tree. So even if something leaks this - // particular fiber, it won't leak anything else. - - fiber.return = null; - fiber.dependencies = null; - fiber.memoizedProps = null; - fiber.memoizedState = null; - fiber.pendingProps = null; - fiber.stateNode = null; // TODO: Move to `commitPassiveUnmountInsideDeletedTreeOnFiber` instead. - - fiber.updateQueue = null; -} + var newState = finishedWork.memoizedState; + var isHidden = newState !== null; + var wasHidden = current !== null && current.memoizedState !== null; -function getHostParentFiber(fiber) { - var parent = fiber.return; + if (finishedWork.mode & ConcurrentMode) { + // Before committing the children, track on the stack whether this + // offscreen subtree was already hidden, so that we don't unmount the + // effects again. + var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden; + var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; + offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden || isHidden; + offscreenSubtreeWasHidden = + prevOffscreenSubtreeWasHidden || wasHidden; + recursivelyTraverseMutationEffects(root, finishedWork); + offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; + offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; + } else { + recursivelyTraverseMutationEffects(root, finishedWork); + } - while (parent !== null) { - if (isHostParent(parent)) { - return parent; - } + commitReconciliationEffects(finishedWork); + var offscreenInstance = finishedWork.stateNode; // TODO: Add explicit effect flag to set _current. - parent = parent.return; - } + offscreenInstance._current = finishedWork; // Offscreen stores pending changes to visibility in `_pendingVisibility`. This is + // to support batching of `attach` and `detach` calls. - throw new Error( - "Expected to find a host parent. This error is likely caused by a bug " + - "in React. Please file an issue." - ); -} + offscreenInstance._visibility &= ~OffscreenDetached; + offscreenInstance._visibility |= + offscreenInstance._pendingVisibility & OffscreenDetached; -function isHostParent(fiber) { - return ( - fiber.tag === HostComponent || - fiber.tag === HostRoot || - false || - false || - fiber.tag === HostPortal - ); -} + if (flags & Visibility) { + // Track the current state on the Offscreen instance so we can + // read it during an event + if (isHidden) { + offscreenInstance._visibility &= ~OffscreenVisible; + } else { + offscreenInstance._visibility |= OffscreenVisible; + } -function getHostSibling(fiber) { - // We're going to search forward into the tree until we find a sibling host - // node. Unfortunately, if multiple insertions are done in a row we have to - // search past them. This leads to exponential search for the next sibling. - // TODO: Find a more efficient way to do this. - var node = fiber; - - siblings: while (true) { - // If we didn't find anything, let's try the next sibling. - while (node.sibling === null) { - if (node.return === null || isHostParent(node.return)) { - // If we pop out of the root or hit the parent the fiber we are the - // last sibling. - return null; - } // $FlowFixMe[incompatible-type] found when upgrading Flow + if (isHidden) { + var isUpdate = current !== null; + var wasHiddenByAncestorOffscreen = + offscreenSubtreeIsHidden || offscreenSubtreeWasHidden; // Only trigger disapper layout effects if: + // - This is an update, not first mount. + // - This Offscreen was not hidden before. + // - Ancestor Offscreen was not hidden in previous commit. + + if (isUpdate && !wasHidden && !wasHiddenByAncestorOffscreen) { + if ((finishedWork.mode & ConcurrentMode) !== NoMode) { + // Disappear the layout effects of all the children + recursivelyTraverseDisappearLayoutEffects(finishedWork); + } + } + } // Offscreen with manual mode manages visibility manually. - node = node.return; - } + if (!isOffscreenManual(finishedWork)) { + // TODO: This needs to run whenever there's an insertion or update + // inside a hidden Offscreen tree. + hideOrUnhideAllChildren(finishedWork, isHidden); + } + } // TODO: Move to passive phase - node.sibling.return = node.return; - node = node.sibling; + if (flags & Update) { + var offscreenQueue = finishedWork.updateQueue; - while ( - node.tag !== HostComponent && - node.tag !== HostText && - true && - node.tag !== DehydratedFragment - ) { - // If it is not host node and, we might have a host node inside it. - // Try to search down until we find one. - if (node.flags & Placement) { - // If we don't have a child, try the siblings instead. - continue siblings; - } // If we don't have a child, try the siblings instead. - // We also skip portals because they are not part of this host tree. - - if (node.child === null || node.tag === HostPortal) { - continue siblings; - } else { - node.child.return = node; - node = node.child; - } - } // Check if this host node is stable or about to be placed. + if (offscreenQueue !== null) { + var _retryQueue = offscreenQueue.retryQueue; - if (!(node.flags & Placement)) { - // Found it! - return node.stateNode; - } - } -} + if (_retryQueue !== null) { + offscreenQueue.retryQueue = null; + attachSuspenseRetryListeners(finishedWork, _retryQueue); + } + } + } -function commitPlacement(finishedWork) { - var parentFiber = getHostParentFiber(finishedWork); + return; + } - switch (parentFiber.tag) { - case HostSingleton: + case SuspenseListComponent: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); - case HostComponent: { - var _parent = parentFiber.stateNode; + if (flags & Update) { + var _retryQueue2 = finishedWork.updateQueue; - if (parentFiber.flags & ContentReset) { - parentFiber.flags &= ~ContentReset; - } + if (_retryQueue2 !== null) { + finishedWork.updateQueue = null; + attachSuspenseRetryListeners(finishedWork, _retryQueue2); + } + } - var _before = getHostSibling(finishedWork); // We only have the top Fiber that was inserted but we need to recurse down its - // children to find all the terminal nodes. + return; + } - insertOrAppendPlacementNode(finishedWork, _before, _parent); - break; - } + case ScopeComponent: { + { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); // TODO: This is a temporary solution that allowed us to transition away + // from React Flare on www. - case HostRoot: - case HostPortal: { - var _parent2 = parentFiber.stateNode.containerInfo; + if (flags & Ref) { + if (current !== null) { + safelyDetachRef(finishedWork, finishedWork.return); + } - var _before2 = getHostSibling(finishedWork); + safelyAttachRef(finishedWork, finishedWork.return); + } - insertOrAppendPlacementNodeIntoContainer( - finishedWork, - _before2, - _parent2 - ); - break; - } + if (flags & Update) { + prepareScopeUpdate(); + } + } - default: - throw new Error( - "Invalid host parent fiber. This error is likely caused by a bug " + - "in React. Please file an issue." - ); - } -} + return; + } -function insertOrAppendPlacementNodeIntoContainer(node, before, parent) { - var tag = node.tag; - var isHost = tag === HostComponent || tag === HostText; + default: { + recursivelyTraverseMutationEffects(root, finishedWork); + commitReconciliationEffects(finishedWork); + return; + } + } + } - if (isHost) { - var stateNode = node.stateNode; + function commitReconciliationEffects(finishedWork) { + // Placement effects (insertions, reorders) can be scheduled on any fiber + // type. They needs to happen after the children effects have fired, but + // before the effects on this fiber have fired. + var flags = finishedWork.flags; - if (before) { - insertInContainerBefore(parent, stateNode, before); - } else { - appendChildToContainer(parent, stateNode); - } - } else if (tag === HostPortal || false); - else { - var child = node.child; + if (flags & Placement) { + try { + commitPlacement(finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } // Clear the "placement" from effect tag so that we know that this is + // inserted, before any life-cycles like componentDidMount gets called. + // TODO: findDOMNode doesn't rely on this any more but isMounted does + // and isMounted is deprecated anyway so we should be able to kill this. - if (child !== null) { - insertOrAppendPlacementNodeIntoContainer(child, before, parent); - var sibling = child.sibling; + finishedWork.flags &= ~Placement; + } - while (sibling !== null) { - insertOrAppendPlacementNodeIntoContainer(sibling, before, parent); - sibling = sibling.sibling; + if (flags & Hydrating) { + finishedWork.flags &= ~Hydrating; } } - } -} -function insertOrAppendPlacementNode(node, before, parent) { - var tag = node.tag; - var isHost = tag === HostComponent || tag === HostText; - - if (isHost) { - var stateNode = node.stateNode; + function commitLayoutEffects(finishedWork, root, committedLanes) { + inProgressLanes = committedLanes; + inProgressRoot = root; + var current = finishedWork.alternate; + commitLayoutEffectOnFiber(root, current, finishedWork); + inProgressLanes = null; + inProgressRoot = null; + } - if (before) { - insertBefore(parent, stateNode, before); - } else { - appendChild(parent, stateNode); - } - } else if (tag === HostPortal || false); - else { - var child = node.child; - - if (child !== null) { - insertOrAppendPlacementNode(child, before, parent); - var sibling = child.sibling; - - while (sibling !== null) { - insertOrAppendPlacementNode(sibling, before, parent); - sibling = sibling.sibling; - } - } - } -} // These are tracked on the stack as we recursively traverse a -// deleted subtree. -// TODO: Update these during the whole mutation phase, not just during -// a deletion. - -var hostParent = null; -var hostParentIsContainer = false; - -function commitDeletionEffects(root, returnFiber, deletedFiber) { - { - // We only have the top Fiber that was deleted but we need to recurse down its - // children to find all the terminal nodes. - // Recursively delete all host nodes from the parent, detach refs, clean - // up mounted layout effects, and call componentWillUnmount. - // We only need to remove the topmost host child in each branch. But then we - // still need to keep traversing to unmount effects, refs, and cWU. TODO: We - // could split this into two separate traversals functions, where the second - // one doesn't include any removeChild logic. This is maybe the same - // function as "disappearLayoutEffects" (or whatever that turns into after - // the layout phase is refactored to use recursion). - // Before starting, find the nearest host parent on the stack so we know - // which instance/container to remove the children from. - // TODO: Instead of searching up the fiber return path on every deletion, we - // can track the nearest host component on the JS stack as we traverse the - // tree during the commit phase. This would make insertions faster, too. - var parent = returnFiber; - - findParent: while (parent !== null) { - switch (parent.tag) { - case HostSingleton: - case HostComponent: { - hostParent = parent.stateNode; - hostParentIsContainer = false; - break findParent; - } + function recursivelyTraverseLayoutEffects(root, parentFiber, lanes) { + var prevDebugFiber = getCurrentFiber(); - case HostRoot: { - hostParent = parent.stateNode.containerInfo; - hostParentIsContainer = true; - break findParent; - } + if (parentFiber.subtreeFlags & LayoutMask) { + var child = parentFiber.child; - case HostPortal: { - hostParent = parent.stateNode.containerInfo; - hostParentIsContainer = true; - break findParent; + while (child !== null) { + setCurrentFiber(child); + var current = child.alternate; + commitLayoutEffectOnFiber(root, current, child); + child = child.sibling; } } - parent = parent.return; - } - - if (hostParent === null) { - throw new Error( - "Expected to find a host parent. This error is likely caused by " + - "a bug in React. Please file an issue." - ); + setCurrentFiber(prevDebugFiber); } - commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber); - hostParent = null; - hostParentIsContainer = false; - } + function disappearLayoutEffects(finishedWork) { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + // TODO (Offscreen) Check: flags & LayoutStatic + if (shouldProfile(finishedWork)) { + try { + startLayoutEffectTimer(); + commitHookEffectListUnmount( + Layout, + finishedWork, + finishedWork.return + ); + } finally { + recordLayoutEffectDuration(finishedWork); + } + } else { + commitHookEffectListUnmount( + Layout, + finishedWork, + finishedWork.return + ); + } - detachFiberMutation(deletedFiber); -} + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; + } -function recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - parent -) { - // TODO: Use a static flag to skip trees that don't have unmount effects - var child = parent.child; - - while (child !== null) { - commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, child); - child = child.sibling; - } -} + case ClassComponent: { + // TODO (Offscreen) Check: flags & RefStatic + safelyDetachRef(finishedWork, finishedWork.return); + var instance = finishedWork.stateNode; -function commitDeletionEffectsOnFiber( - finishedRoot, - nearestMountedAncestor, - deletedFiber -) { - onCommitUnmount(deletedFiber); // The cases in this outer switch modify the stack before they traverse - // into their subtree. There are simpler cases in the inner switch - // that don't modify the stack. + if (typeof instance.componentWillUnmount === "function") { + safelyCallComponentWillUnmount( + finishedWork, + finishedWork.return, + instance + ); + } - switch (deletedFiber.tag) { - case HostHoistable: + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; + } - case HostSingleton: + case HostHoistable: + case HostSingleton: + case HostComponent: { + // TODO (Offscreen) Check: flags & RefStatic + safelyDetachRef(finishedWork, finishedWork.return); + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; + } - case HostComponent: { - if (!offscreenSubtreeWasHidden) { - safelyDetachRef(deletedFiber, nearestMountedAncestor); - } // Intentional fallthrough to next branch - } + case OffscreenComponent: { + // TODO (Offscreen) Check: flags & RefStatic + safelyDetachRef(finishedWork, finishedWork.return); + var isHidden = finishedWork.memoizedState !== null; - case HostText: { - // We only need to remove the nearest host child. Set the host parent - // to `null` on the stack to indicate that nested children don't - // need to be removed. - { - var _prevHostParent = hostParent; - var _prevHostParentIsContainer = hostParentIsContainer; - hostParent = null; - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - hostParent = _prevHostParent; - hostParentIsContainer = _prevHostParentIsContainer; - - if (hostParent !== null) { - // Now that all the child effects have unmounted, we can remove the - // node from the tree. - if (hostParentIsContainer) { - removeChildFromContainer(hostParent, deletedFiber.stateNode); - } else { - removeChild(hostParent, deletedFiber.stateNode); + if (isHidden); + else { + recursivelyTraverseDisappearLayoutEffects(finishedWork); } + + break; + } + + default: { + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; } } + } - return; + function recursivelyTraverseDisappearLayoutEffects(parentFiber) { + // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) + var child = parentFiber.child; + + while (child !== null) { + disappearLayoutEffects(child); + child = child.sibling; + } } - case DehydratedFragment: { - { - var hydrationCallbacks = finishedRoot.hydrationCallbacks; + function reappearLayoutEffects( + finishedRoot, + current, + finishedWork, // This function visits both newly finished work and nodes that were re-used + // from a previously committed tree. We cannot check non-static flags if the + // node was reused. + includeWorkInProgressEffects + ) { + // Turn on layout effects in a tree that previously disappeared. + var flags = finishedWork.flags; - if (hydrationCallbacks !== null) { - var onDeleted = hydrationCallbacks.onDeleted; + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); // TODO: Check flags & LayoutStatic - if (onDeleted) { - onDeleted(deletedFiber.stateNode); - } + commitHookLayoutEffects(finishedWork, Layout); + break; } - } // Dehydrated fragments don't have any children - // Delete the dehydrated suspense boundary and all of its content. - { - if (hostParent !== null) { - if (hostParentIsContainer) { - clearSuspenseBoundaryFromContainer(); - } else { - clearSuspenseBoundary(); - } - } - } + case ClassComponent: { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); // TODO: Check for LayoutStatic flag - return; - } + var instance = finishedWork.stateNode; - case HostPortal: { - { - // When we go into a portal, it becomes the parent to remove from. - var _prevHostParent2 = hostParent; - var _prevHostParentIsContainer2 = hostParentIsContainer; - hostParent = deletedFiber.stateNode.containerInfo; - hostParentIsContainer = true; - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - hostParent = _prevHostParent2; - hostParentIsContainer = _prevHostParentIsContainer2; - } + if (typeof instance.componentDidMount === "function") { + try { + instance.componentDidMount(); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } // Commit any callbacks that would have fired while the component + // was hidden. - return; - } + var updateQueue = finishedWork.updateQueue; - case FunctionComponent: - case ForwardRef: - case MemoComponent: - case SimpleMemoComponent: { - if (!offscreenSubtreeWasHidden) { - var updateQueue = deletedFiber.updateQueue; + if (updateQueue !== null) { + commitHiddenCallbacks(updateQueue, instance); + } // If this is newly finished work, check for setState callbacks - if (updateQueue !== null) { - var lastEffect = updateQueue.lastEffect; + if (includeWorkInProgressEffects && flags & Callback) { + commitClassCallbacks(finishedWork); + } // TODO: Check flags & RefStatic - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; + safelyAttachRef(finishedWork, finishedWork.return); + break; + } + // Unlike commitLayoutEffectsOnFiber, we don't need to handle HostRoot + // because this function only visits nodes that are inside an + // Offscreen fiber. + // case HostRoot: { + // ... + // } - do { - var tag = effect.tag; - var inst = effect.inst; - var destroy = inst.destroy; - - if (destroy !== undefined) { - if ((tag & Insertion) !== NoFlags) { - inst.destroy = undefined; - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - ); - } else if ((tag & Layout) !== NoFlags) { - if (enableSchedulingProfiler) { - markComponentLayoutEffectUnmountStarted(deletedFiber); - } + case HostHoistable: + case HostSingleton: + case HostComponent: { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); // Renderers may schedule work to be done after host components are mounted + // (eg DOM renderer may schedule auto-focus for inputs and form controls). + // These effects should only be committed when components are first mounted, + // aka when there is no current/alternate. - if (shouldProfile(deletedFiber)) { - startLayoutEffectTimer(); - inst.destroy = undefined; - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - ); - recordLayoutEffectDuration(deletedFiber); - } else { - inst.destroy = undefined; - safelyCallDestroy( - deletedFiber, - nearestMountedAncestor, - destroy - ); - } + if ( + includeWorkInProgressEffects && + current === null && + flags & Update + ) { + commitHostComponentMount(finishedWork); + } // TODO: Check flags & Ref - if (enableSchedulingProfiler) { - markComponentLayoutEffectUnmountStopped(); - } - } - } + safelyAttachRef(finishedWork, finishedWork.return); + break; + } + + case Profiler: { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); // TODO: Figure out how Profiler updates should work with Offscreen - effect = effect.next; - } while (effect !== firstEffect); + if (includeWorkInProgressEffects && flags & Update) { + commitProfilerUpdate(finishedWork, current); } + + break; } - } - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; - } + case SuspenseComponent: { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); // TODO: Figure out how Suspense hydration callbacks should work - case ClassComponent: { - if (!offscreenSubtreeWasHidden) { - safelyDetachRef(deletedFiber, nearestMountedAncestor); - var instance = deletedFiber.stateNode; + break; + } - if (typeof instance.componentWillUnmount === "function") { - safelyCallComponentWillUnmount( - deletedFiber, - nearestMountedAncestor, - instance + case OffscreenComponent: { + var offscreenState = finishedWork.memoizedState; + var isHidden = offscreenState !== null; + + if (isHidden); + else { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects + ); + } // TODO: Check flags & Ref + + safelyAttachRef(finishedWork, finishedWork.return); + break; + } + + default: { + recursivelyTraverseReappearLayoutEffects( + finishedRoot, + finishedWork, + includeWorkInProgressEffects ); + break; } } - - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; } - case ScopeComponent: { - { - safelyDetachRef(deletedFiber, nearestMountedAncestor); - } + function recursivelyTraverseReappearLayoutEffects( + finishedRoot, + parentFiber, + includeWorkInProgressEffects + ) { + // This function visits both newly finished work and nodes that were re-used + // from a previously committed tree. We cannot check non-static flags if the + // node was reused. + var childShouldIncludeWorkInProgressEffects = + includeWorkInProgressEffects && + (parentFiber.subtreeFlags & LayoutMask) !== NoFlags$1; // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; - } - - case OffscreenComponent: { - safelyDetachRef(deletedFiber, nearestMountedAncestor); - - if (deletedFiber.mode & ConcurrentMode) { - // If this offscreen component is hidden, we already unmounted it. Before - // deleting the children, track that it's already unmounted so that we - // don't attempt to unmount the effects again. - // TODO: If the tree is hidden, in most cases we should be able to skip - // over the nested children entirely. An exception is we haven't yet found - // the topmost host node to delete, which we already track on the stack. - // But the other case is portals, which need to be detached no matter how - // deeply they are nested. We should use a subtree flag to track whether a - // subtree includes a nested portal. - var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; - offscreenSubtreeWasHidden = - prevOffscreenSubtreeWasHidden || deletedFiber.memoizedState !== null; - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; - } else { - recursivelyTraverseDeletionEffects( + var prevDebugFiber = getCurrentFiber(); + var child = parentFiber.child; + + while (child !== null) { + var current = child.alternate; + reappearLayoutEffects( finishedRoot, - nearestMountedAncestor, - deletedFiber + current, + child, + childShouldIncludeWorkInProgressEffects ); + child = child.sibling; } - break; - } - - default: { - recursivelyTraverseDeletionEffects( - finishedRoot, - nearestMountedAncestor, - deletedFiber - ); - return; + setCurrentFiber(prevDebugFiber); } - } -} - -function commitSuspenseCallback(finishedWork) { - // TODO: Move this to passive phase - var newState = finishedWork.memoizedState; - if (newState !== null) { - var suspenseCallback = finishedWork.memoizedProps.suspenseCallback; + function commitHookPassiveMountEffects(finishedWork, hookFlags) { + if (shouldProfile(finishedWork)) { + startPassiveEffectTimer(); - if (typeof suspenseCallback === "function") { - var retryQueue = finishedWork.updateQueue; + try { + commitHookEffectListMount(hookFlags, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } - if (retryQueue !== null) { - suspenseCallback(new Set(retryQueue)); - } - } else { - if (suspenseCallback !== undefined) { - error("Unexpected type for suspenseCallback."); + recordPassiveEffectDuration(finishedWork); + } else { + try { + commitHookEffectListMount(hookFlags, finishedWork); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } } } - } -} -function getRetryCache(finishedWork) { - // TODO: Unify the interface for the retry cache so we don't have to switch - // on the tag like this. - switch (finishedWork.tag) { - case SuspenseComponent: - case SuspenseListComponent: { - var retryCache = finishedWork.stateNode; + function commitOffscreenPassiveMountEffects( + current, + finishedWork, + instance + ) { + { + var previousCache = null; + + if ( + current !== null && + current.memoizedState !== null && + current.memoizedState.cachePool !== null + ) { + previousCache = current.memoizedState.cachePool.pool; + } + + var nextCache = null; + + if ( + finishedWork.memoizedState !== null && + finishedWork.memoizedState.cachePool !== null + ) { + nextCache = finishedWork.memoizedState.cachePool.pool; + } // Retain/release the cache used for pending (suspended) nodes. + // Note that this is only reached in the non-suspended/visible case: + // when the content is suspended/hidden, the retain/release occurs + // via the parent Suspense component (see case above). + + if (nextCache !== previousCache) { + if (nextCache != null) { + retainCache(nextCache); + } - if (retryCache === null) { - retryCache = finishedWork.stateNode = new PossiblyWeakSet(); + if (previousCache != null) { + releaseCache(previousCache); + } + } } - return retryCache; - } + if (enableTransitionTracing) { + // TODO: Pre-rendering should not be counted as part of a transition. We + // may add separate logs for pre-rendering, but it's not part of the + // primary metrics. + var offscreenState = finishedWork.memoizedState; + var queue = finishedWork.updateQueue; + var isHidden = offscreenState !== null; - case OffscreenComponent: { - var instance = finishedWork.stateNode; - var _retryCache = instance._retryCache; + if (queue !== null) { + if (isHidden) { + var transitions = queue.transitions; - if (_retryCache === null) { - _retryCache = instance._retryCache = new PossiblyWeakSet(); - } + if (transitions !== null) { + transitions.forEach(function (transition) { + // Add all the transitions saved in the update queue during + // the render phase (ie the transitions associated with this boundary) + // into the transitions set. + if (instance._transitions === null) { + instance._transitions = new Set(); + } - return _retryCache; - } + instance._transitions.add(transition); + }); + } - default: { - throw new Error( - "Unexpected Suspense handler tag (" + - finishedWork.tag + - "). This is a " + - "bug in React." - ); - } - } -} + var markerInstances = queue.markerInstances; -function detachOffscreenInstance(instance) { - var fiber = instance._current; + if (markerInstances !== null) { + markerInstances.forEach(function (markerInstance) { + var markerTransitions = markerInstance.transitions; // There should only be a few tracing marker transitions because + // they should be only associated with the transition that + // caused them - if (fiber === null) { - throw new Error( - "Calling Offscreen.detach before instance handle has been set." - ); - } + if (markerTransitions !== null) { + markerTransitions.forEach(function (transition) { + if (instance._transitions === null) { + instance._transitions = new Set(); + } else if (instance._transitions.has(transition)) { + if (markerInstance.pendingBoundaries === null) { + markerInstance.pendingBoundaries = new Map(); + } - if ((instance._pendingVisibility & OffscreenDetached) !== NoFlags$1) { - // The instance is already detached, this is a noop. - return; - } // TODO: There is an opportunity to optimise this by not entering commit phase - // and unmounting effects directly. + if (instance._pendingMarkers === null) { + instance._pendingMarkers = new Set(); + } - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + instance._pendingMarkers.add(markerInstance); + } + }); + } + }); + } + } - if (root !== null) { - instance._pendingVisibility |= OffscreenDetached; - scheduleUpdateOnFiber(root, fiber, SyncLane); - } -} -function attachOffscreenInstance(instance) { - var fiber = instance._current; + finishedWork.updateQueue = null; + } - if (fiber === null) { - throw new Error( - "Calling Offscreen.detach before instance handle has been set." - ); - } + commitTransitionProgress(finishedWork); // TODO: Refactor this into an if/else branch - if ((instance._pendingVisibility & OffscreenDetached) === NoFlags$1) { - // The instance is already attached, this is a noop. - return; - } + if (!isHidden) { + instance._transitions = null; + instance._pendingMarkers = null; + } + } + } - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + function commitCachePassiveMountEffect(current, finishedWork) { + { + var previousCache = null; - if (root !== null) { - instance._pendingVisibility &= ~OffscreenDetached; - scheduleUpdateOnFiber(root, fiber, SyncLane); - } -} + if (finishedWork.alternate !== null) { + previousCache = finishedWork.alternate.memoizedState.cache; + } -function attachSuspenseRetryListeners(finishedWork, wakeables) { - // If this boundary just timed out, then it will have a set of wakeables. - // For each wakeable, attach a listener so that when it resolves, React - // attempts to re-render the boundary in the primary (pre-timeout) state. - var retryCache = getRetryCache(finishedWork); - wakeables.forEach(function (wakeable) { - // Memoize using the boundary fiber to prevent redundant listeners. - var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); + var nextCache = finishedWork.memoizedState.cache; // Retain/release the cache. In theory the cache component + // could be "borrowing" a cache instance owned by some parent, + // in which case we could avoid retaining/releasing. But it + // is non-trivial to determine when that is the case, so we + // always retain/release. - if (!retryCache.has(wakeable)) { - retryCache.add(wakeable); + if (nextCache !== previousCache) { + retainCache(nextCache); - { - if (isDevToolsPresent) { - if (inProgressLanes !== null && inProgressRoot !== null) { - // If we have pending work still, associate the original updaters with it. - restorePendingUpdaters(inProgressRoot, inProgressLanes); - } else { - throw Error( - "Expected finished root and lanes to be set. This is a bug in React." - ); + if (previousCache != null) { + releaseCache(previousCache); } } } - - wakeable.then(retry, retry); } - }); -} // This function detects when a Suspense boundary goes from visible to hidden. -// It returns false if the boundary is already hidden. -// TODO: Use an effect tag. -function isSuspenseBoundaryBeingHidden(current, finishedWork) { - if (current !== null) { - var oldState = current.memoizedState; + function commitTracingMarkerPassiveMountEffect(finishedWork) { + // Get the transitions that were initiatized during the render + // and add a start transition callback for each of them + // We will only call this on initial mount of the tracing marker + // only if there are no suspense children + var instance = finishedWork.stateNode; - if (oldState === null || oldState.dehydrated !== null) { - var newState = finishedWork.memoizedState; - return newState !== null && newState.dehydrated === null; + if ( + instance.transitions !== null && + instance.pendingBoundaries === null + ) { + addMarkerCompleteCallbackToPendingTransition( + finishedWork.memoizedProps.name, + instance.transitions + ); + instance.transitions = null; + instance.pendingBoundaries = null; + instance.aborts = null; + instance.name = null; + } } - } - return false; -} -function commitMutationEffects(root, finishedWork, committedLanes) { - inProgressLanes = committedLanes; - inProgressRoot = root; - setCurrentFiber(finishedWork); - commitMutationEffectsOnFiber(finishedWork, root); - setCurrentFiber(finishedWork); - inProgressLanes = null; - inProgressRoot = null; -} + function commitPassiveMountEffects( + root, + finishedWork, + committedLanes, + committedTransitions + ) { + setCurrentFiber(finishedWork); + commitPassiveMountOnFiber( + root, + finishedWork, + committedLanes, + committedTransitions + ); + resetCurrentFiber(); + } -function recursivelyTraverseMutationEffects(root, parentFiber, lanes) { - // Deletions effects can be scheduled on any fiber type. They need to happen - // before the children effects hae fired. - var deletions = parentFiber.deletions; + function recursivelyTraversePassiveMountEffects( + root, + parentFiber, + committedLanes, + committedTransitions + ) { + var prevDebugFiber = getCurrentFiber(); - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var childToDelete = deletions[i]; + if (parentFiber.subtreeFlags & PassiveMask) { + var child = parentFiber.child; - try { - commitDeletionEffects(root, parentFiber, childToDelete); - } catch (error) { - captureCommitPhaseError(childToDelete, parentFiber, error); + while (child !== null) { + setCurrentFiber(child); + commitPassiveMountOnFiber( + root, + child, + committedLanes, + committedTransitions + ); + child = child.sibling; + } } - } - } - var prevDebugFiber = getCurrentFiber(); - - if (parentFiber.subtreeFlags & MutationMask) { - var child = parentFiber.child; - - while (child !== null) { - setCurrentFiber(child); - commitMutationEffectsOnFiber(child, root); - child = child.sibling; + setCurrentFiber(prevDebugFiber); } - } - setCurrentFiber(prevDebugFiber); -} + function commitPassiveMountOnFiber( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ) { + // When updating this function, also update reconnectPassiveEffects, which does + // most of the same things when an offscreen tree goes from hidden -> visible, + // or when toggling effects inside a hidden tree. + var flags = finishedWork.flags; -function commitMutationEffectsOnFiber(finishedWork, root, lanes) { - var current = finishedWork.alternate; - var flags = finishedWork.flags; // The effect flag should be checked *after* we refine the type of fiber, - // because the fiber tag is more specific. An exception is any flag related - // to reconciliation, because those can be set on all fiber types. - - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case MemoComponent: - case SimpleMemoComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - - if (flags & Update) { - try { - commitHookEffectListUnmount( - Insertion | HasEffect, + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + recursivelyTraversePassiveMountEffects( + finishedRoot, finishedWork, - finishedWork.return + committedLanes, + committedTransitions ); - commitHookEffectListMount(Insertion | HasEffect, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } // Layout effects are destroyed during the mutation phase so that all - // destroy functions for all fibers are called before any create functions. - // This prevents sibling component effects from interfering with each other, - // e.g. a destroy function in one component should never override a ref set - // by a create function in another component during the same commit. - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - commitHookEffectListUnmount( - Layout | HasEffect, - finishedWork, - finishedWork.return - ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + if (flags & Passive$1) { + commitHookPassiveMountEffects(finishedWork, Passive | HasEffect); } - recordLayoutEffectDuration(finishedWork); - } else { - try { - commitHookEffectListUnmount( - Layout | HasEffect, - finishedWork, - finishedWork.return - ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + break; } - } - return; - } + case HostRoot: { + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); - case ClassComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + if (flags & Passive$1) { + { + var previousCache = null; - if (flags & Ref) { - if (current !== null) { - safelyDetachRef(current, current.return); - } - } + if (finishedWork.alternate !== null) { + previousCache = finishedWork.alternate.memoizedState.cache; + } - if (flags & Callback && offscreenSubtreeIsHidden) { - var updateQueue = finishedWork.updateQueue; + var nextCache = finishedWork.memoizedState.cache; // Retain/release the root cache. + // Note that on initial mount, previousCache and nextCache will be the same + // and this retain won't occur. To counter this, we instead retain the HostRoot's + // initial cache when creating the root itself (see createFiberRoot() in + // ReactFiberRoot.js). Subsequent updates that change the cache are reflected + // here, such that previous/next caches are retained correctly. - if (updateQueue !== null) { - deferHiddenCallbacks(updateQueue); - } - } + if (nextCache !== previousCache) { + retainCache(nextCache); - return; - } + if (previousCache != null) { + releaseCache(previousCache); + } + } + } - case HostHoistable: + if (enableTransitionTracing) { + // Get the transitions that were initiatized during the render + // and add a start transition callback for each of them + var root = finishedWork.stateNode; + var incompleteTransitions = root.incompleteTransitions; // Initial render - case HostSingleton: + if (committedTransitions !== null) { + committedTransitions.forEach(function (transition) { + addTransitionStartCallbackToPendingTransition(transition); + }); + clearTransitionsForLanes(finishedRoot, committedLanes); + } - case HostComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + incompleteTransitions.forEach( + function (markerInstance, transition) { + var pendingBoundaries = markerInstance.pendingBoundaries; + + if ( + pendingBoundaries === null || + pendingBoundaries.size === 0 + ) { + if (markerInstance.aborts === null) { + addTransitionCompleteCallbackToPendingTransition( + transition + ); + } - if (flags & Ref) { - if (current !== null) { - safelyDetachRef(current, current.return); + incompleteTransitions.delete(transition); + } + } + ); + clearTransitionsForLanes(finishedRoot, committedLanes); + } + } + + break; } - } - { - // TODO: ContentReset gets cleared by the children during the commit - // phase. This is a refactor hazard because it means we must read - // flags the flags after `commitReconciliationEffects` has already run; - // the order matters. We should refactor so that ContentReset does not - // rely on mutating the flag during commit. Like by setting a flag - // during the render phase instead. - if (finishedWork.flags & ContentReset) { - var instance = finishedWork.stateNode; + case LegacyHiddenComponent: { + { + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); - try { - resetTextContent(instance); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + if (flags & Passive$1) { + var current = finishedWork.alternate; + var instance = finishedWork.stateNode; + commitOffscreenPassiveMountEffects( + current, + finishedWork, + instance + ); + } + } + + break; + } + + case OffscreenComponent: { + // TODO: Pass `current` as argument to this function + var _instance3 = finishedWork.stateNode; + var nextState = finishedWork.memoizedState; + var isHidden = nextState !== null; + + if (isHidden) { + if (_instance3._visibility & OffscreenPassiveEffectsConnected) { + // The effects are currently connected. Update them. + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); + } else { + if (finishedWork.mode & ConcurrentMode) { + // The effects are currently disconnected. Since the tree is hidden, + // don't connect them. This also applies to the initial render. + { + // "Atomic" effects are ones that need to fire on every commit, + // even during pre-rendering. An example is updating the reference + // count on cache instances. + recursivelyTraverseAtomicPassiveEffects( + finishedRoot, + finishedWork + ); + } + } else { + // Legacy Mode: Fire the effects even if the tree is hidden. + _instance3._visibility |= OffscreenPassiveEffectsConnected; + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); + } + } + } else { + // Tree is visible + if (_instance3._visibility & OffscreenPassiveEffectsConnected) { + // The effects are currently connected. Update them. + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); + } else { + // The effects are currently disconnected. Reconnect them, while also + // firing effects inside newly mounted trees. This also applies to + // the initial render. + _instance3._visibility |= OffscreenPassiveEffectsConnected; + var includeWorkInProgressEffects = + (finishedWork.subtreeFlags & PassiveMask) !== NoFlags$1; + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); + } } - } - if (flags & Update) { - var _instance2 = finishedWork.stateNode; - - if (_instance2 != null) { - // Commit the work prepared earlier. - var newProps = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps - // as the newProps. The updatePayload will contain the real change in - // this case. + if (flags & Passive$1) { + var _current = finishedWork.alternate; + commitOffscreenPassiveMountEffects( + _current, + finishedWork, + _instance3 + ); + } - var oldProps = current !== null ? current.memoizedProps : newProps; - var type = finishedWork.type; // TODO: Type the updateQueue to be specific to host components. + break; + } - var _updatePayload = finishedWork.updateQueue; - finishedWork.updateQueue = null; + case CacheComponent: { + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); - try { - commitUpdate( - _instance2, - _updatePayload, - type, - oldProps, - newProps, - finishedWork - ); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + if (flags & Passive$1) { + // TODO: Pass `current` as argument to this function + var _current2 = finishedWork.alternate; + commitCachePassiveMountEffect(_current2, finishedWork); } - } - } - return; - } - - case HostText: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + break; + } - if (flags & Update) { - { - if (finishedWork.stateNode === null) { - throw new Error( - "This should have a text node initialized. This error is likely " + - "caused by a bug in React. Please file an issue." + case TracingMarkerComponent: { + if (enableTransitionTracing) { + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions ); - } - var textInstance = finishedWork.stateNode; - var newText = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps - // as the newProps. The updatePayload will contain the real change in - // this case. + if (flags & Passive$1) { + commitTracingMarkerPassiveMountEffect(finishedWork); + } - var oldText = current !== null ? current.memoizedProps : newText; + break; + } // Intentional fallthrough to next branch + } - try { - commitTextUpdate(textInstance, oldText, newText); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + default: { + recursivelyTraversePassiveMountEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ); + break; } } - - return; } - case HostRoot: { - { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - } + function recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + parentFiber, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ) { + // This function visits both newly finished work and nodes that were re-used + // from a previously committed tree. We cannot check non-static flags if the + // node was reused. + var childShouldIncludeWorkInProgressEffects = + includeWorkInProgressEffects && + (parentFiber.subtreeFlags & PassiveMask) !== NoFlags$1; // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) - return; - } + var prevDebugFiber = getCurrentFiber(); + var child = parentFiber.child; - case HostPortal: { - { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + while (child !== null) { + reconnectPassiveEffects( + finishedRoot, + child, + committedLanes, + committedTransitions, + childShouldIncludeWorkInProgressEffects + ); + child = child.sibling; } - return; + setCurrentFiber(prevDebugFiber); } - case SuspenseComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); // TODO: We should mark a flag on the Suspense fiber itself, rather than - // relying on the Offscreen fiber having a flag also being marked. The - // reason is that this offscreen fiber might not be part of the work-in- - // progress tree! It could have been reused from a previous render. This - // doesn't lead to incorrect behavior because we don't rely on the flag - // check alone; we also compare the states explicitly below. But for - // modeling purposes, we _should_ be able to rely on the flag check alone. - // So this is a bit fragile. - // - // Also, all this logic could/should move to the passive phase so it - // doesn't block paint. - - var offscreenFiber = finishedWork.child; + function reconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, // This function visits both newly finished work and nodes that were re-used + // from a previously committed tree. We cannot check non-static flags if the + // node was reused. + includeWorkInProgressEffects + ) { + var flags = finishedWork.flags; - if (offscreenFiber.flags & Visibility) { - // Throttle the appearance and disappearance of Suspense fallbacks. - var isShowingFallback = finishedWork.memoizedState !== null; - var wasShowingFallback = - current !== null && current.memoizedState !== null; + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); // TODO: Check for PassiveStatic flag - if (alwaysThrottleRetries) { - if (isShowingFallback !== wasShowingFallback) { - // A fallback is either appearing or disappearing. - markCommitTimeOfFallback(); - } - } else { - if (isShowingFallback && !wasShowingFallback) { - // Old behavior. Only mark when a fallback appears, not when - // it disappears. - markCommitTimeOfFallback(); - } + commitHookPassiveMountEffects(finishedWork, Passive); + break; } - } + // Unlike commitPassiveMountOnFiber, we don't need to handle HostRoot + // because this function only visits nodes that are inside an + // Offscreen fiber. + // case HostRoot: { + // ... + // } - if (flags & Update) { - try { - commitSuspenseCallback(finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + case LegacyHiddenComponent: { + { + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); - var retryQueue = finishedWork.updateQueue; + if (includeWorkInProgressEffects && flags & Passive$1) { + // TODO: Pass `current` as argument to this function + var current = finishedWork.alternate; + var instance = finishedWork.stateNode; + commitOffscreenPassiveMountEffects( + current, + finishedWork, + instance + ); + } + } - if (retryQueue !== null) { - finishedWork.updateQueue = null; - attachSuspenseRetryListeners(finishedWork, retryQueue); + break; } - } - return; - } + case OffscreenComponent: { + var _instance4 = finishedWork.stateNode; + var nextState = finishedWork.memoizedState; + var isHidden = nextState !== null; - case OffscreenComponent: { - if (flags & Ref) { - if (current !== null) { - safelyDetachRef(current, current.return); - } - } + if (isHidden) { + if (_instance4._visibility & OffscreenPassiveEffectsConnected) { + // The effects are currently connected. Update them. + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); + } else { + if (finishedWork.mode & ConcurrentMode) { + // The effects are currently disconnected. Since the tree is hidden, + // don't connect them. This also applies to the initial render. + { + // "Atomic" effects are ones that need to fire on every commit, + // even during pre-rendering. An example is updating the reference + // count on cache instances. + recursivelyTraverseAtomicPassiveEffects( + finishedRoot, + finishedWork + ); + } + } else { + // Legacy Mode: Fire the effects even if the tree is hidden. + _instance4._visibility |= OffscreenPassiveEffectsConnected; + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); + } + } + } else { + // Tree is visible + // Since we're already inside a reconnecting tree, it doesn't matter + // whether the effects are currently connected. In either case, we'll + // continue traversing the tree and firing all the effects. + // + // We do need to set the "connected" flag on the instance, though. + _instance4._visibility |= OffscreenPassiveEffectsConnected; + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); + } - var newState = finishedWork.memoizedState; - var isHidden = newState !== null; - var wasHidden = current !== null && current.memoizedState !== null; - - if (finishedWork.mode & ConcurrentMode) { - // Before committing the children, track on the stack whether this - // offscreen subtree was already hidden, so that we don't unmount the - // effects again. - var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden; - var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; - offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden || isHidden; - offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden || wasHidden; - recursivelyTraverseMutationEffects(root, finishedWork); - offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; - offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; - } else { - recursivelyTraverseMutationEffects(root, finishedWork); - } + if (includeWorkInProgressEffects && flags & Passive$1) { + // TODO: Pass `current` as argument to this function + var _current3 = finishedWork.alternate; + commitOffscreenPassiveMountEffects( + _current3, + finishedWork, + _instance4 + ); + } - commitReconciliationEffects(finishedWork); - var offscreenInstance = finishedWork.stateNode; // TODO: Add explicit effect flag to set _current. + break; + } - offscreenInstance._current = finishedWork; // Offscreen stores pending changes to visibility in `_pendingVisibility`. This is - // to support batching of `attach` and `detach` calls. + case CacheComponent: { + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); - offscreenInstance._visibility &= ~OffscreenDetached; - offscreenInstance._visibility |= - offscreenInstance._pendingVisibility & OffscreenDetached; + if (includeWorkInProgressEffects && flags & Passive$1) { + // TODO: Pass `current` as argument to this function + var _current4 = finishedWork.alternate; + commitCachePassiveMountEffect(_current4, finishedWork); + } - if (flags & Visibility) { - // Track the current state on the Offscreen instance so we can - // read it during an event - if (isHidden) { - offscreenInstance._visibility &= ~OffscreenVisible; - } else { - offscreenInstance._visibility |= OffscreenVisible; + break; } - if (isHidden) { - var isUpdate = current !== null; - var wasHiddenByAncestorOffscreen = - offscreenSubtreeIsHidden || offscreenSubtreeWasHidden; // Only trigger disapper layout effects if: - // - This is an update, not first mount. - // - This Offscreen was not hidden before. - // - Ancestor Offscreen was not hidden in previous commit. + case TracingMarkerComponent: { + if (enableTransitionTracing) { + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); - if (isUpdate && !wasHidden && !wasHiddenByAncestorOffscreen) { - if ((finishedWork.mode & ConcurrentMode) !== NoMode) { - // Disappear the layout effects of all the children - recursivelyTraverseDisappearLayoutEffects(finishedWork); + if (includeWorkInProgressEffects && flags & Passive$1) { + commitTracingMarkerPassiveMountEffect(finishedWork); } - } - } // Offscreen with manual mode manages visibility manually. - if (!isOffscreenManual(finishedWork)) { - // TODO: This needs to run whenever there's an insertion or update - // inside a hidden Offscreen tree. - hideOrUnhideAllChildren(finishedWork, isHidden); + break; + } // Intentional fallthrough to next branch } - } // TODO: Move to passive phase - - if (flags & Update) { - var offscreenQueue = finishedWork.updateQueue; - if (offscreenQueue !== null) { - var _retryQueue = offscreenQueue.retryQueue; - - if (_retryQueue !== null) { - offscreenQueue.retryQueue = null; - attachSuspenseRetryListeners(finishedWork, _retryQueue); - } + default: { + recursivelyTraverseReconnectPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions, + includeWorkInProgressEffects + ); + break; } } - - return; } - case SuspenseListComponent: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); + function recursivelyTraverseAtomicPassiveEffects( + finishedRoot, + parentFiber, + committedLanes, + committedTransitions + ) { + // "Atomic" effects are ones that need to fire on every commit, even during + // pre-rendering. We call this function when traversing a hidden tree whose + // regular effects are currently disconnected. + var prevDebugFiber = getCurrentFiber(); // TODO: Add special flag for atomic effects - if (flags & Update) { - var _retryQueue2 = finishedWork.updateQueue; + if (parentFiber.subtreeFlags & PassiveMask) { + var child = parentFiber.child; - if (_retryQueue2 !== null) { - finishedWork.updateQueue = null; - attachSuspenseRetryListeners(finishedWork, _retryQueue2); + while (child !== null) { + setCurrentFiber(child); + commitAtomicPassiveEffects(finishedRoot, child); + child = child.sibling; } } - return; + setCurrentFiber(prevDebugFiber); } - case ScopeComponent: { - { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); // TODO: This is a temporary solution that allowed us to transition away - // from React Flare on www. + function commitAtomicPassiveEffects( + finishedRoot, + finishedWork, + committedLanes, + committedTransitions + ) { + // "Atomic" effects are ones that need to fire on every commit, even during + // pre-rendering. We call this function when traversing a hidden tree whose + // regular effects are currently disconnected. + var flags = finishedWork.flags; - if (flags & Ref) { - if (current !== null) { - safelyDetachRef(finishedWork, finishedWork.return); + switch (finishedWork.tag) { + case OffscreenComponent: { + recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork); + + if (flags & Passive$1) { + // TODO: Pass `current` as argument to this function + var current = finishedWork.alternate; + var instance = finishedWork.stateNode; + commitOffscreenPassiveMountEffects(current, finishedWork, instance); } - safelyAttachRef(finishedWork, finishedWork.return); - } - - if (flags & Update) { - prepareScopeUpdate(); + break; } - } - - return; - } - - default: { - recursivelyTraverseMutationEffects(root, finishedWork); - commitReconciliationEffects(finishedWork); - return; - } - } -} - -function commitReconciliationEffects(finishedWork) { - // Placement effects (insertions, reorders) can be scheduled on any fiber - // type. They needs to happen after the children effects have fired, but - // before the effects on this fiber have fired. - var flags = finishedWork.flags; - - if (flags & Placement) { - try { - commitPlacement(finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } // Clear the "placement" from effect tag so that we know that this is - // inserted, before any life-cycles like componentDidMount gets called. - // TODO: findDOMNode doesn't rely on this any more but isMounted does - // and isMounted is deprecated anyway so we should be able to kill this. - - finishedWork.flags &= ~Placement; - } - - if (flags & Hydrating) { - finishedWork.flags &= ~Hydrating; - } -} -function commitLayoutEffects(finishedWork, root, committedLanes) { - inProgressLanes = committedLanes; - inProgressRoot = root; - var current = finishedWork.alternate; - commitLayoutEffectOnFiber(root, current, finishedWork); - inProgressLanes = null; - inProgressRoot = null; -} - -function recursivelyTraverseLayoutEffects(root, parentFiber, lanes) { - var prevDebugFiber = getCurrentFiber(); + case CacheComponent: { + recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork); - if (parentFiber.subtreeFlags & LayoutMask) { - var child = parentFiber.child; - - while (child !== null) { - setCurrentFiber(child); - var current = child.alternate; - commitLayoutEffectOnFiber(root, current, child); - child = child.sibling; - } - } + if (flags & Passive$1) { + // TODO: Pass `current` as argument to this function + var _current5 = finishedWork.alternate; + commitCachePassiveMountEffect(_current5, finishedWork); + } - setCurrentFiber(prevDebugFiber); -} + break; + } -function disappearLayoutEffects(finishedWork) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case MemoComponent: - case SimpleMemoComponent: { - // TODO (Offscreen) Check: flags & LayoutStatic - if (shouldProfile(finishedWork)) { - try { - startLayoutEffectTimer(); - commitHookEffectListUnmount( - Layout, - finishedWork, - finishedWork.return - ); - } finally { - recordLayoutEffectDuration(finishedWork); + default: { + recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork); + break; } - } else { - commitHookEffectListUnmount(Layout, finishedWork, finishedWork.return); } - - recursivelyTraverseDisappearLayoutEffects(finishedWork); - break; } - case ClassComponent: { - // TODO (Offscreen) Check: flags & RefStatic - safelyDetachRef(finishedWork, finishedWork.return); - var instance = finishedWork.stateNode; - - if (typeof instance.componentWillUnmount === "function") { - safelyCallComponentWillUnmount( - finishedWork, - finishedWork.return, - instance - ); - } - - recursivelyTraverseDisappearLayoutEffects(finishedWork); - break; - } + function commitPassiveUnmountEffects(finishedWork) { + setCurrentFiber(finishedWork); + commitPassiveUnmountOnFiber(finishedWork); + resetCurrentFiber(); + } // If we're inside a brand new tree, or a tree that was already visible, then we + // should only suspend host components that have a ShouldSuspendCommit flag. + // Components without it haven't changed since the last commit, so we can skip + // over those. + // + // When we enter a tree that is being revealed (going from hidden -> visible), + // we need to suspend _any_ component that _may_ suspend. Even if they're + // already in the "current" tree. Because their visibility has changed, the + // browser may not have prerendered them yet. So we check the MaySuspendCommit + // flag instead. - case HostHoistable: - case HostSingleton: - case HostComponent: { - // TODO (Offscreen) Check: flags & RefStatic - safelyDetachRef(finishedWork, finishedWork.return); - recursivelyTraverseDisappearLayoutEffects(finishedWork); - break; + var suspenseyCommitFlag = ShouldSuspendCommit; + function accumulateSuspenseyCommit(finishedWork) { + accumulateSuspenseyCommitOnFiber(finishedWork); } - case OffscreenComponent: { - // TODO (Offscreen) Check: flags & RefStatic - safelyDetachRef(finishedWork, finishedWork.return); - var isHidden = finishedWork.memoizedState !== null; + function recursivelyAccumulateSuspenseyCommit(parentFiber) { + if (parentFiber.subtreeFlags & suspenseyCommitFlag) { + var child = parentFiber.child; - if (isHidden); - else { - recursivelyTraverseDisappearLayoutEffects(finishedWork); + while (child !== null) { + accumulateSuspenseyCommitOnFiber(child); + child = child.sibling; + } } - - break; - } - - default: { - recursivelyTraverseDisappearLayoutEffects(finishedWork); - break; } - } -} -function recursivelyTraverseDisappearLayoutEffects(parentFiber) { - // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) - var child = parentFiber.child; + function accumulateSuspenseyCommitOnFiber(fiber) { + switch (fiber.tag) { + case HostHoistable: { + recursivelyAccumulateSuspenseyCommit(fiber); - while (child !== null) { - disappearLayoutEffects(child); - child = child.sibling; - } -} + if (fiber.flags & suspenseyCommitFlag) { + if (fiber.memoizedState !== null) { + suspendResource(); + } + } -function reappearLayoutEffects( - finishedRoot, - current, - finishedWork, // This function visits both newly finished work and nodes that were re-used - // from a previously committed tree. We cannot check non-static flags if the - // node was reused. - includeWorkInProgressEffects -) { - // Turn on layout effects in a tree that previously disappeared. - var flags = finishedWork.flags; - - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); // TODO: Check flags & LayoutStatic + break; + } - commitHookLayoutEffects(finishedWork, Layout); - break; - } + case HostComponent: { + recursivelyAccumulateSuspenseyCommit(fiber); - case ClassComponent: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); // TODO: Check for LayoutStatic flag + break; + } - var instance = finishedWork.stateNode; + case HostRoot: + case HostPortal: { + { + recursivelyAccumulateSuspenseyCommit(fiber); + } - if (typeof instance.componentDidMount === "function") { - try { - instance.componentDidMount(); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); + break; } - } // Commit any callbacks that would have fired while the component - // was hidden. - var updateQueue = finishedWork.updateQueue; + case OffscreenComponent: { + var isHidden = fiber.memoizedState !== null; - if (updateQueue !== null) { - commitHiddenCallbacks(updateQueue, instance); - } // If this is newly finished work, check for setState callbacks - - if (includeWorkInProgressEffects && flags & Callback) { - commitClassCallbacks(finishedWork); - } // TODO: Check flags & RefStatic - - safelyAttachRef(finishedWork, finishedWork.return); - break; - } - // Unlike commitLayoutEffectsOnFiber, we don't need to handle HostRoot - // because this function only visits nodes that are inside an - // Offscreen fiber. - // case HostRoot: { - // ... - // } - - case HostHoistable: - case HostSingleton: - case HostComponent: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); // Renderers may schedule work to be done after host components are mounted - // (eg DOM renderer may schedule auto-focus for inputs and form controls). - // These effects should only be committed when components are first mounted, - // aka when there is no current/alternate. + if (isHidden); + else { + var current = fiber.alternate; + var wasHidden = current !== null && current.memoizedState !== null; + + if (wasHidden) { + // This tree is being revealed. Visit all newly visible suspensey + // instances, even if they're in the current tree. + var prevFlags = suspenseyCommitFlag; + suspenseyCommitFlag = MaySuspendCommit; + recursivelyAccumulateSuspenseyCommit(fiber); + suspenseyCommitFlag = prevFlags; + } else { + recursivelyAccumulateSuspenseyCommit(fiber); + } + } - if (includeWorkInProgressEffects && current === null && flags & Update) { - commitHostComponentMount(finishedWork); - } // TODO: Check flags & Ref + break; + } - safelyAttachRef(finishedWork, finishedWork.return); - break; + default: { + recursivelyAccumulateSuspenseyCommit(fiber); + } + } } - case Profiler: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); // TODO: Figure out how Profiler updates should work with Offscreen + function detachAlternateSiblings(parentFiber) { + // A fiber was deleted from this parent fiber, but it's still part of the + // previous (alternate) parent fiber's list of children. Because children + // are a linked list, an earlier sibling that's still alive will be + // connected to the deleted fiber via its `alternate`: + // + // live fiber --alternate--> previous live fiber --sibling--> deleted + // fiber + // + // We can't disconnect `alternate` on nodes that haven't been deleted yet, + // but we can disconnect the `sibling` and `child` pointers. + var previousFiber = parentFiber.alternate; - if (includeWorkInProgressEffects && flags & Update) { - commitProfilerUpdate(finishedWork, current); - } + if (previousFiber !== null) { + var detachedChild = previousFiber.child; - break; - } + if (detachedChild !== null) { + previousFiber.child = null; - case SuspenseComponent: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); // TODO: Figure out how Suspense hydration callbacks should work + do { + // $FlowFixMe[incompatible-use] found when upgrading Flow + var detachedSibling = detachedChild.sibling; // $FlowFixMe[incompatible-use] found when upgrading Flow - break; + detachedChild.sibling = null; + detachedChild = detachedSibling; + } while (detachedChild !== null); + } + } } - case OffscreenComponent: { - var offscreenState = finishedWork.memoizedState; - var isHidden = offscreenState !== null; - - if (isHidden); - else { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, + function commitHookPassiveUnmountEffects( + finishedWork, + nearestMountedAncestor, + hookFlags + ) { + if (shouldProfile(finishedWork)) { + startPassiveEffectTimer(); + commitHookEffectListUnmount( + hookFlags, finishedWork, - includeWorkInProgressEffects + nearestMountedAncestor ); - } // TODO: Check flags & Ref - - safelyAttachRef(finishedWork, finishedWork.return); - break; + recordPassiveEffectDuration(finishedWork); + } else { + commitHookEffectListUnmount( + hookFlags, + finishedWork, + nearestMountedAncestor + ); + } } - default: { - recursivelyTraverseReappearLayoutEffects( - finishedRoot, - finishedWork, - includeWorkInProgressEffects - ); - break; - } - } -} + function recursivelyTraversePassiveUnmountEffects(parentFiber) { + // Deletions effects can be scheduled on any fiber type. They need to happen + // before the children effects have fired. + var deletions = parentFiber.deletions; -function recursivelyTraverseReappearLayoutEffects( - finishedRoot, - parentFiber, - includeWorkInProgressEffects -) { - // This function visits both newly finished work and nodes that were re-used - // from a previously committed tree. We cannot check non-static flags if the - // node was reused. - var childShouldIncludeWorkInProgressEffects = - includeWorkInProgressEffects && - (parentFiber.subtreeFlags & LayoutMask) !== NoFlags$1; // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) - - var prevDebugFiber = getCurrentFiber(); - var child = parentFiber.child; - - while (child !== null) { - var current = child.alternate; - reappearLayoutEffects( - finishedRoot, - current, - child, - childShouldIncludeWorkInProgressEffects - ); - child = child.sibling; - } + if ((parentFiber.flags & ChildDeletion) !== NoFlags$1) { + if (deletions !== null) { + for (var i = 0; i < deletions.length; i++) { + var childToDelete = deletions[i]; // TODO: Convert this to use recursion - setCurrentFiber(prevDebugFiber); -} + nextEffect = childToDelete; + commitPassiveUnmountEffectsInsideOfDeletedTree_begin( + childToDelete, + parentFiber + ); + } + } -function commitHookPassiveMountEffects(finishedWork, hookFlags) { - if (shouldProfile(finishedWork)) { - startPassiveEffectTimer(); + detachAlternateSiblings(parentFiber); + } - try { - commitHookEffectListMount(hookFlags, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } + var prevDebugFiber = getCurrentFiber(); // TODO: Split PassiveMask into separate masks for mount and unmount? - recordPassiveEffectDuration(finishedWork); - } else { - try { - commitHookEffectListMount(hookFlags, finishedWork); - } catch (error) { - captureCommitPhaseError(finishedWork, finishedWork.return, error); - } - } -} + if (parentFiber.subtreeFlags & PassiveMask) { + var child = parentFiber.child; -function commitOffscreenPassiveMountEffects(current, finishedWork, instance) { - { - var previousCache = null; + while (child !== null) { + setCurrentFiber(child); + commitPassiveUnmountOnFiber(child); + child = child.sibling; + } + } - if ( - current !== null && - current.memoizedState !== null && - current.memoizedState.cachePool !== null - ) { - previousCache = current.memoizedState.cachePool.pool; + setCurrentFiber(prevDebugFiber); } - var nextCache = null; + function commitPassiveUnmountOnFiber(finishedWork) { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + recursivelyTraversePassiveUnmountEffects(finishedWork); + + if (finishedWork.flags & Passive$1) { + commitHookPassiveUnmountEffects( + finishedWork, + finishedWork.return, + Passive | HasEffect + ); + } - if ( - finishedWork.memoizedState !== null && - finishedWork.memoizedState.cachePool !== null - ) { - nextCache = finishedWork.memoizedState.cachePool.pool; - } // Retain/release the cache used for pending (suspended) nodes. - // Note that this is only reached in the non-suspended/visible case: - // when the content is suspended/hidden, the retain/release occurs - // via the parent Suspense component (see case above). + break; + } - if (nextCache !== previousCache) { - if (nextCache != null) { - retainCache(nextCache); - } + case OffscreenComponent: { + var instance = finishedWork.stateNode; + var nextState = finishedWork.memoizedState; + var isHidden = nextState !== null; + + if ( + isHidden && + instance._visibility & OffscreenPassiveEffectsConnected && // For backwards compatibility, don't unmount when a tree suspends. In + // the future we may change this to unmount after a delay. + (finishedWork.return === null || + finishedWork.return.tag !== SuspenseComponent) + ) { + // The effects are currently connected. Disconnect them. + // TODO: Add option or heuristic to delay before disconnecting the + // effects. Then if the tree reappears before the delay has elapsed, we + // can skip toggling the effects entirely. + instance._visibility &= ~OffscreenPassiveEffectsConnected; + recursivelyTraverseDisconnectPassiveEffects(finishedWork); + } else { + recursivelyTraversePassiveUnmountEffects(finishedWork); + } + + break; + } - if (previousCache != null) { - releaseCache(previousCache); + default: { + recursivelyTraversePassiveUnmountEffects(finishedWork); + break; + } } } - } - if (enableTransitionTracing) { - // TODO: Pre-rendering should not be counted as part of a transition. We - // may add separate logs for pre-rendering, but it's not part of the - // primary metrics. - var offscreenState = finishedWork.memoizedState; - var queue = finishedWork.updateQueue; - var isHidden = offscreenState !== null; + function recursivelyTraverseDisconnectPassiveEffects(parentFiber) { + // Deletions effects can be scheduled on any fiber type. They need to happen + // before the children effects have fired. + var deletions = parentFiber.deletions; - if (queue !== null) { - if (isHidden) { - var transitions = queue.transitions; - - if (transitions !== null) { - transitions.forEach(function (transition) { - // Add all the transitions saved in the update queue during - // the render phase (ie the transitions associated with this boundary) - // into the transitions set. - if (instance._transitions === null) { - instance._transitions = new Set(); - } + if ((parentFiber.flags & ChildDeletion) !== NoFlags$1) { + if (deletions !== null) { + for (var i = 0; i < deletions.length; i++) { + var childToDelete = deletions[i]; // TODO: Convert this to use recursion - instance._transitions.add(transition); - }); + nextEffect = childToDelete; + commitPassiveUnmountEffectsInsideOfDeletedTree_begin( + childToDelete, + parentFiber + ); + } } - var markerInstances = queue.markerInstances; - - if (markerInstances !== null) { - markerInstances.forEach(function (markerInstance) { - var markerTransitions = markerInstance.transitions; // There should only be a few tracing marker transitions because - // they should be only associated with the transition that - // caused them + detachAlternateSiblings(parentFiber); + } - if (markerTransitions !== null) { - markerTransitions.forEach(function (transition) { - if (instance._transitions === null) { - instance._transitions = new Set(); - } else if (instance._transitions.has(transition)) { - if (markerInstance.pendingBoundaries === null) { - markerInstance.pendingBoundaries = new Map(); - } + var prevDebugFiber = getCurrentFiber(); // TODO: Check PassiveStatic flag - if (instance._pendingMarkers === null) { - instance._pendingMarkers = new Set(); - } + var child = parentFiber.child; - instance._pendingMarkers.add(markerInstance); - } - }); - } - }); - } + while (child !== null) { + setCurrentFiber(child); + disconnectPassiveEffect(child); + child = child.sibling; } - finishedWork.updateQueue = null; + setCurrentFiber(prevDebugFiber); } - commitTransitionProgress(finishedWork); // TODO: Refactor this into an if/else branch + function disconnectPassiveEffect(finishedWork) { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + // TODO: Check PassiveStatic flag + commitHookPassiveUnmountEffects( + finishedWork, + finishedWork.return, + Passive + ); // When disconnecting passive effects, we fire the effects in the same + // order as during a deletiong: parent before child - if (!isHidden) { - instance._transitions = null; - instance._pendingMarkers = null; - } - } -} + recursivelyTraverseDisconnectPassiveEffects(finishedWork); + break; + } + + case OffscreenComponent: { + var instance = finishedWork.stateNode; + + if (instance._visibility & OffscreenPassiveEffectsConnected) { + instance._visibility &= ~OffscreenPassiveEffectsConnected; + recursivelyTraverseDisconnectPassiveEffects(finishedWork); + } -function commitCachePassiveMountEffect(current, finishedWork) { - { - var previousCache = null; + break; + } - if (finishedWork.alternate !== null) { - previousCache = finishedWork.alternate.memoizedState.cache; + default: { + recursivelyTraverseDisconnectPassiveEffects(finishedWork); + break; + } + } } - var nextCache = finishedWork.memoizedState.cache; // Retain/release the cache. In theory the cache component - // could be "borrowing" a cache instance owned by some parent, - // in which case we could avoid retaining/releasing. But it - // is non-trivial to determine when that is the case, so we - // always retain/release. + function commitPassiveUnmountEffectsInsideOfDeletedTree_begin( + deletedSubtreeRoot, + nearestMountedAncestor + ) { + while (nextEffect !== null) { + var fiber = nextEffect; // Deletion effects fire in parent -> child order + // TODO: Check if fiber has a PassiveStatic flag - if (nextCache !== previousCache) { - retainCache(nextCache); + setCurrentFiber(fiber); + commitPassiveUnmountInsideDeletedTreeOnFiber( + fiber, + nearestMountedAncestor + ); + resetCurrentFiber(); + var child = fiber.child; // TODO: Only traverse subtree if it has a PassiveStatic flag. - if (previousCache != null) { - releaseCache(previousCache); + if (child !== null) { + child.return = fiber; + nextEffect = child; + } else { + commitPassiveUnmountEffectsInsideOfDeletedTree_complete( + deletedSubtreeRoot + ); + } } } - } -} -function commitTracingMarkerPassiveMountEffect(finishedWork) { - // Get the transitions that were initiatized during the render - // and add a start transition callback for each of them - // We will only call this on initial mount of the tracing marker - // only if there are no suspense children - var instance = finishedWork.stateNode; - - if (instance.transitions !== null && instance.pendingBoundaries === null) { - addMarkerCompleteCallbackToPendingTransition( - finishedWork.memoizedProps.name, - instance.transitions - ); - instance.transitions = null; - instance.pendingBoundaries = null; - instance.aborts = null; - instance.name = null; - } -} + function commitPassiveUnmountEffectsInsideOfDeletedTree_complete( + deletedSubtreeRoot + ) { + while (nextEffect !== null) { + var fiber = nextEffect; + var sibling = fiber.sibling; + var returnFiber = fiber.return; // Recursively traverse the entire deleted tree and clean up fiber fields. + // This is more aggressive than ideal, and the long term goal is to only + // have to detach the deleted tree at the root. -function commitPassiveMountEffects( - root, - finishedWork, - committedLanes, - committedTransitions -) { - setCurrentFiber(finishedWork); - commitPassiveMountOnFiber( - root, - finishedWork, - committedLanes, - committedTransitions - ); - resetCurrentFiber(); -} + detachFiberAfterEffects(fiber); -function recursivelyTraversePassiveMountEffects( - root, - parentFiber, - committedLanes, - committedTransitions -) { - var prevDebugFiber = getCurrentFiber(); + if (fiber === deletedSubtreeRoot) { + nextEffect = null; + return; + } - if (parentFiber.subtreeFlags & PassiveMask) { - var child = parentFiber.child; + if (sibling !== null) { + sibling.return = returnFiber; + nextEffect = sibling; + return; + } - while (child !== null) { - setCurrentFiber(child); - commitPassiveMountOnFiber( - root, - child, - committedLanes, - committedTransitions - ); - child = child.sibling; + nextEffect = returnFiber; + } } - } - setCurrentFiber(prevDebugFiber); -} + function commitPassiveUnmountInsideDeletedTreeOnFiber( + current, + nearestMountedAncestor + ) { + switch (current.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + commitHookPassiveUnmountEffects( + current, + nearestMountedAncestor, + Passive + ); + break; + } + // TODO: run passive unmount effects when unmounting a root. + // Because passive unmount effects are not currently run, + // the cache instance owned by the root will never be freed. + // When effects are run, the cache should be freed here: + // case HostRoot: { + // if (enableCache) { + // const cache = current.memoizedState.cache; + // releaseCache(cache); + // } + // break; + // } + + case LegacyHiddenComponent: + case OffscreenComponent: { + { + if ( + current.memoizedState !== null && + current.memoizedState.cachePool !== null + ) { + var cache = current.memoizedState.cachePool.pool; // Retain/release the cache used for pending (suspended) nodes. + // Note that this is only reached in the non-suspended/visible case: + // when the content is suspended/hidden, the retain/release occurs + // via the parent Suspense component (see case above). -function commitPassiveMountOnFiber( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions -) { - // When updating this function, also update reconnectPassiveEffects, which does - // most of the same things when an offscreen tree goes from hidden -> visible, - // or when toggling effects inside a hidden tree. - var flags = finishedWork.flags; - - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); + if (cache != null) { + retainCache(cache); + } + } + } - if (flags & Passive$1) { - commitHookPassiveMountEffects(finishedWork, Passive | HasEffect); - } + break; + } - break; - } + case SuspenseComponent: { + if (enableTransitionTracing) { + // We need to mark this fiber's parents as deleted + var offscreenFiber = current.child; + var instance = offscreenFiber.stateNode; + var transitions = instance._transitions; - case HostRoot: { - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); + if (transitions !== null) { + var abortReason = { + reason: "suspense", + name: current.memoizedProps.unstable_name || null + }; - if (flags & Passive$1) { - { - var previousCache = null; + if ( + current.memoizedState === null || + current.memoizedState.dehydrated === null + ) { + abortParentMarkerTransitionsForDeletedFiber( + offscreenFiber, + abortReason, + transitions, + instance, + true + ); - if (finishedWork.alternate !== null) { - previousCache = finishedWork.alternate.memoizedState.cache; + if (nearestMountedAncestor !== null) { + abortParentMarkerTransitionsForDeletedFiber( + nearestMountedAncestor, + abortReason, + transitions, + instance, + false + ); + } + } + } } - var nextCache = finishedWork.memoizedState.cache; // Retain/release the root cache. - // Note that on initial mount, previousCache and nextCache will be the same - // and this retain won't occur. To counter this, we instead retain the HostRoot's - // initial cache when creating the root itself (see createFiberRoot() in - // ReactFiberRoot.js). Subsequent updates that change the cache are reflected - // here, such that previous/next caches are retained correctly. + break; + } - if (nextCache !== previousCache) { - retainCache(nextCache); + case CacheComponent: { + { + var _cache = current.memoizedState.cache; + releaseCache(_cache); + } - if (previousCache != null) { - releaseCache(previousCache); + break; + } + + case TracingMarkerComponent: { + if (enableTransitionTracing) { + // We need to mark this fiber's parents as deleted + var _instance5 = current.stateNode; + var _transitions = _instance5.transitions; + + if (_transitions !== null) { + var _abortReason = { + reason: "marker", + name: current.memoizedProps.name + }; + abortParentMarkerTransitionsForDeletedFiber( + current, + _abortReason, + _transitions, + null, + true + ); + + if (nearestMountedAncestor !== null) { + abortParentMarkerTransitionsForDeletedFiber( + nearestMountedAncestor, + _abortReason, + _transitions, + null, + false + ); + } } } + + break; } + } + } - if (enableTransitionTracing) { - // Get the transitions that were initiatized during the render - // and add a start transition callback for each of them - var root = finishedWork.stateNode; - var incompleteTransitions = root.incompleteTransitions; // Initial render - - if (committedTransitions !== null) { - committedTransitions.forEach(function (transition) { - addTransitionStartCallbackToPendingTransition(transition); - }); - clearTransitionsForLanes(finishedRoot, committedLanes); + function invokeLayoutEffectMountInDEV(fiber) { + { + // We don't need to re-check StrictEffectsMode here. + // This function is only called if that check has already passed. + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + try { + commitHookEffectListMount(Layout | HasEffect, fiber); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } + + break; } - incompleteTransitions.forEach(function (markerInstance, transition) { - var pendingBoundaries = markerInstance.pendingBoundaries; + case ClassComponent: { + var instance = fiber.stateNode; - if (pendingBoundaries === null || pendingBoundaries.size === 0) { - if (markerInstance.aborts === null) { - addTransitionCompleteCallbackToPendingTransition(transition); + if (typeof instance.componentDidMount === "function") { + try { + instance.componentDidMount(); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); } - - incompleteTransitions.delete(transition); } - }); - clearTransitionsForLanes(finishedRoot, committedLanes); + + break; + } } } - - break; } - case LegacyHiddenComponent: { + function invokePassiveEffectMountInDEV(fiber) { { - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); + // We don't need to re-check StrictEffectsMode here. + // This function is only called if that check has already passed. + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + try { + commitHookEffectListMount(Passive | HasEffect, fiber); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } - if (flags & Passive$1) { - var current = finishedWork.alternate; - var instance = finishedWork.stateNode; - commitOffscreenPassiveMountEffects(current, finishedWork, instance); + break; + } } } - - break; } - case OffscreenComponent: { - // TODO: Pass `current` as argument to this function - var _instance3 = finishedWork.stateNode; - var nextState = finishedWork.memoizedState; - var isHidden = nextState !== null; - - if (isHidden) { - if (_instance3._visibility & OffscreenPassiveEffectsConnected) { - // The effects are currently connected. Update them. - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); - } else { - if (finishedWork.mode & ConcurrentMode) { - // The effects are currently disconnected. Since the tree is hidden, - // don't connect them. This also applies to the initial render. - { - // "Atomic" effects are ones that need to fire on every commit, - // even during pre-rendering. An example is updating the reference - // count on cache instances. - recursivelyTraverseAtomicPassiveEffects( - finishedRoot, - finishedWork + function invokeLayoutEffectUnmountInDEV(fiber) { + { + // We don't need to re-check StrictEffectsMode here. + // This function is only called if that check has already passed. + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + try { + commitHookEffectListUnmount( + Layout | HasEffect, + fiber, + fiber.return ); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); } - } else { - // Legacy Mode: Fire the effects even if the tree is hidden. - _instance3._visibility |= OffscreenPassiveEffectsConnected; - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); + + break; + } + + case ClassComponent: { + var instance = fiber.stateNode; + + if (typeof instance.componentWillUnmount === "function") { + safelyCallComponentWillUnmount(fiber, fiber.return, instance); + } + + break; } - } - } else { - // Tree is visible - if (_instance3._visibility & OffscreenPassiveEffectsConnected) { - // The effects are currently connected. Update them. - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); - } else { - // The effects are currently disconnected. Reconnect them, while also - // firing effects inside newly mounted trees. This also applies to - // the initial render. - _instance3._visibility |= OffscreenPassiveEffectsConnected; - var includeWorkInProgressEffects = - (finishedWork.subtreeFlags & PassiveMask) !== NoFlags$1; - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); } } + } - if (flags & Passive$1) { - var _current = finishedWork.alternate; - commitOffscreenPassiveMountEffects(_current, finishedWork, _instance3); + function invokePassiveEffectUnmountInDEV(fiber) { + { + // We don't need to re-check StrictEffectsMode here. + // This function is only called if that check has already passed. + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + try { + commitHookEffectListUnmount( + Passive | HasEffect, + fiber, + fiber.return + ); + } catch (error) { + captureCommitPhaseError(fiber, fiber.return, error); + } + } + } } + } - break; + function getCacheSignal() { + var cache = readContext(CacheContext); + return cache.controller.signal; } - case CacheComponent: { - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); + function getCacheForType(resourceType) { + var cache = readContext(CacheContext); + var cacheForType = cache.data.get(resourceType); - if (flags & Passive$1) { - // TODO: Pass `current` as argument to this function - var _current2 = finishedWork.alternate; - commitCachePassiveMountEffect(_current2, finishedWork); + if (cacheForType === undefined) { + cacheForType = resourceType(); + cache.data.set(resourceType, cacheForType); } - break; + return cacheForType; } - case TracingMarkerComponent: { - if (enableTransitionTracing) { - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); + var DefaultCacheDispatcher = { + getCacheSignal: getCacheSignal, + getCacheForType: getCacheForType + }; + + if (typeof Symbol === "function" && Symbol.for) { + var symbolFor = Symbol.for; + symbolFor("selector.component"); + symbolFor("selector.has_pseudo_class"); + symbolFor("selector.role"); + symbolFor("selector.test_id"); + symbolFor("selector.text"); + } - if (flags & Passive$1) { - commitTracingMarkerPassiveMountEffect(finishedWork); + var ReactCurrentActQueue$1 = ReactSharedInternals.ReactCurrentActQueue; + function isLegacyActEnvironment(fiber) { + { + // Legacy mode. We preserve the behavior of React 17's act. It assumes an + // act environment whenever `jest` is defined, but you can still turn off + // spurious warnings by setting IS_REACT_ACT_ENVIRONMENT explicitly + // to false. + // $FlowFixMe[cannot-resolve-name] Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global + typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" // $FlowFixMe[cannot-resolve-name] + ? IS_REACT_ACT_ENVIRONMENT + : undefined; // $FlowFixMe[cannot-resolve-name] - Flow doesn't know about jest + return warnsIfNotActing; + } + } + function isConcurrentActEnvironment() { + { + var isReactActEnvironmentGlobal = // $FlowFixMe[cannot-resolve-name] Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global + typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" // $FlowFixMe[cannot-resolve-name] + ? IS_REACT_ACT_ENVIRONMENT + : undefined; + + if ( + !isReactActEnvironmentGlobal && + ReactCurrentActQueue$1.current !== null + ) { + // TODO: Include link to relevant documentation page. + error( + "The current testing environment is not configured to support " + + "act(...)" + ); } - break; - } // Intentional fallthrough to next branch - } + return isReactActEnvironmentGlobal; + } + } + + var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; + var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, + ReactCurrentCache = ReactSharedInternals.ReactCurrentCache, + ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner, + ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig, + ReactCurrentActQueue = ReactSharedInternals.ReactCurrentActQueue; + var NoContext = + /* */ + 0; + var BatchedContext = + /* */ + 1; + var RenderContext = + /* */ + 2; + var CommitContext = + /* */ + 4; + var RootInProgress = 0; + var RootFatalErrored = 1; + var RootErrored = 2; + var RootSuspended = 3; + var RootSuspendedWithDelay = 4; + var RootCompleted = 5; + var RootDidNotComplete = 6; // Describes where we are in the React execution stack + + var executionContext = NoContext; // The root we're working on + + var workInProgressRoot = null; // The fiber we're working on + + var workInProgress = null; // The lanes we're rendering + + var workInProgressRootRenderLanes = NoLanes; + var NotSuspended = 0; + var SuspendedOnError = 1; + var SuspendedOnData = 2; + var SuspendedOnImmediate = 3; + var SuspendedOnInstance = 4; + var SuspendedOnInstanceAndReadyToContinue = 5; + var SuspendedOnDeprecatedThrowPromise = 6; + var SuspendedAndReadyToContinue = 7; + var SuspendedOnHydration = 8; // When this is true, the work-in-progress fiber just suspended (or errored) and + // we've yet to unwind the stack. In some cases, we may yield to the main thread + // after this happens. If the fiber is pinged before we resume, we can retry + // immediately instead of unwinding the stack. + + var workInProgressSuspendedReason = NotSuspended; + var workInProgressThrownValue = null; // Whether a ping listener was attached during this render. This is slightly + // different that whether something suspended, because we don't add multiple + // listeners to a promise we've already seen (per root and lane). + + var workInProgressRootDidAttachPingListener = false; // A contextual version of workInProgressRootRenderLanes. It is a superset of + // the lanes that we started working on at the root. When we enter a subtree + // that is currently hidden, we add the lanes that would have committed if + // the hidden tree hadn't been deferred. This is modified by the + // HiddenContext module. + // + // Most things in the work loop should deal with workInProgressRootRenderLanes. + // Most things in begin/complete phases should deal with entangledRenderLanes. - default: { - recursivelyTraversePassiveMountEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions - ); - break; - } - } -} + var entangledRenderLanes = NoLanes; // Whether to root completed, errored, suspended, etc. -function recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - parentFiber, - committedLanes, - committedTransitions, - includeWorkInProgressEffects -) { - // This function visits both newly finished work and nodes that were re-used - // from a previously committed tree. We cannot check non-static flags if the - // node was reused. - var childShouldIncludeWorkInProgressEffects = - includeWorkInProgressEffects && - (parentFiber.subtreeFlags & PassiveMask) !== NoFlags$1; // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) - - var prevDebugFiber = getCurrentFiber(); - var child = parentFiber.child; - - while (child !== null) { - reconnectPassiveEffects( - finishedRoot, - child, - committedLanes, - committedTransitions, - childShouldIncludeWorkInProgressEffects - ); - child = child.sibling; - } + var workInProgressRootExitStatus = RootInProgress; // A fatal error, if one is thrown - setCurrentFiber(prevDebugFiber); -} + var workInProgressRootFatalError = null; // The work left over by components that were visited during this render. Only + // includes unprocessed updates, not work in bailed out children. -function reconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, // This function visits both newly finished work and nodes that were re-used - // from a previously committed tree. We cannot check non-static flags if the - // node was reused. - includeWorkInProgressEffects -) { - var flags = finishedWork.flags; - - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); // TODO: Check for PassiveStatic flag + var workInProgressRootSkippedLanes = NoLanes; // Lanes that were updated (in an interleaved event) during this render. - commitHookPassiveMountEffects(finishedWork, Passive); - break; - } - // Unlike commitPassiveMountOnFiber, we don't need to handle HostRoot - // because this function only visits nodes that are inside an - // Offscreen fiber. - // case HostRoot: { - // ... - // } + var workInProgressRootInterleavedUpdatedLanes = NoLanes; // Lanes that were updated during the render phase (*not* an interleaved event). - case LegacyHiddenComponent: { - { - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); + var workInProgressRootPingedLanes = NoLanes; // If this lane scheduled deferred work, this is the lane of the deferred task. - if (includeWorkInProgressEffects && flags & Passive$1) { - // TODO: Pass `current` as argument to this function - var current = finishedWork.alternate; - var instance = finishedWork.stateNode; - commitOffscreenPassiveMountEffects(current, finishedWork, instance); - } - } + var workInProgressDeferredLane = NoLane; // Errors that are thrown during the render phase. - break; - } + var workInProgressRootConcurrentErrors = null; // These are errors that we recovered from without surfacing them to the UI. + // We will log them once the tree commits. - case OffscreenComponent: { - var _instance4 = finishedWork.stateNode; - var nextState = finishedWork.memoizedState; - var isHidden = nextState !== null; + var workInProgressRootRecoverableErrors = null; // The most recent time we either committed a fallback, or when a fallback was + // filled in with the resolved UI. This lets us throttle the appearance of new + // content as it streams in, to minimize jank. + // TODO: Think of a better name for this variable? - if (isHidden) { - if (_instance4._visibility & OffscreenPassiveEffectsConnected) { - // The effects are currently connected. Update them. - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); - } else { - if (finishedWork.mode & ConcurrentMode) { - // The effects are currently disconnected. Since the tree is hidden, - // don't connect them. This also applies to the initial render. - { - // "Atomic" effects are ones that need to fire on every commit, - // even during pre-rendering. An example is updating the reference - // count on cache instances. - recursivelyTraverseAtomicPassiveEffects( - finishedRoot, - finishedWork - ); - } - } else { - // Legacy Mode: Fire the effects even if the tree is hidden. - _instance4._visibility |= OffscreenPassiveEffectsConnected; - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); - } - } - } else { - // Tree is visible - // Since we're already inside a reconnecting tree, it doesn't matter - // whether the effects are currently connected. In either case, we'll - // continue traversing the tree and firing all the effects. - // - // We do need to set the "connected" flag on the instance, though. - _instance4._visibility |= OffscreenPassiveEffectsConnected; - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); - } + var globalMostRecentFallbackTime = 0; + var FALLBACK_THROTTLE_MS = 300; // The absolute time for when we should start giving up on rendering + // more and prefer CPU suspense heuristics instead. - if (includeWorkInProgressEffects && flags & Passive$1) { - // TODO: Pass `current` as argument to this function - var _current3 = finishedWork.alternate; - commitOffscreenPassiveMountEffects(_current3, finishedWork, _instance4); - } + var workInProgressRootRenderTargetTime = Infinity; // How long a render is supposed to take before we start following CPU + // suspense heuristics and opt out of rendering more content. - break; + var RENDER_TIMEOUT_MS = 500; + var workInProgressTransitions = null; + function getWorkInProgressTransitions() { + return workInProgressTransitions; } + var currentPendingTransitionCallbacks = null; + var currentEndTime = null; + function addTransitionStartCallbackToPendingTransition(transition) { + if (enableTransitionTracing) { + if (currentPendingTransitionCallbacks === null) { + currentPendingTransitionCallbacks = { + transitionStart: [], + transitionProgress: null, + transitionComplete: null, + markerProgress: null, + markerIncomplete: null, + markerComplete: null + }; + } - case CacheComponent: { - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); + if (currentPendingTransitionCallbacks.transitionStart === null) { + currentPendingTransitionCallbacks.transitionStart = []; + } - if (includeWorkInProgressEffects && flags & Passive$1) { - // TODO: Pass `current` as argument to this function - var _current4 = finishedWork.alternate; - commitCachePassiveMountEffect(_current4, finishedWork); + currentPendingTransitionCallbacks.transitionStart.push(transition); } - - break; } - - case TracingMarkerComponent: { + function addMarkerProgressCallbackToPendingTransition( + markerName, + transitions, + pendingBoundaries + ) { if (enableTransitionTracing) { - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); + if (currentPendingTransitionCallbacks === null) { + currentPendingTransitionCallbacks = { + transitionStart: null, + transitionProgress: null, + transitionComplete: null, + markerProgress: new Map(), + markerIncomplete: null, + markerComplete: null + }; + } - if (includeWorkInProgressEffects && flags & Passive$1) { - commitTracingMarkerPassiveMountEffect(finishedWork); + if (currentPendingTransitionCallbacks.markerProgress === null) { + currentPendingTransitionCallbacks.markerProgress = new Map(); } - break; - } // Intentional fallthrough to next branch + currentPendingTransitionCallbacks.markerProgress.set(markerName, { + pendingBoundaries: pendingBoundaries, + transitions: transitions + }); + } } + function addMarkerIncompleteCallbackToPendingTransition( + markerName, + transitions, + aborts + ) { + if (enableTransitionTracing) { + if (currentPendingTransitionCallbacks === null) { + currentPendingTransitionCallbacks = { + transitionStart: null, + transitionProgress: null, + transitionComplete: null, + markerProgress: null, + markerIncomplete: new Map(), + markerComplete: null + }; + } - default: { - recursivelyTraverseReconnectPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions, - includeWorkInProgressEffects - ); - break; - } - } -} + if (currentPendingTransitionCallbacks.markerIncomplete === null) { + currentPendingTransitionCallbacks.markerIncomplete = new Map(); + } -function recursivelyTraverseAtomicPassiveEffects( - finishedRoot, - parentFiber, - committedLanes, - committedTransitions -) { - // "Atomic" effects are ones that need to fire on every commit, even during - // pre-rendering. We call this function when traversing a hidden tree whose - // regular effects are currently disconnected. - var prevDebugFiber = getCurrentFiber(); // TODO: Add special flag for atomic effects + currentPendingTransitionCallbacks.markerIncomplete.set(markerName, { + transitions: transitions, + aborts: aborts + }); + } + } + function addMarkerCompleteCallbackToPendingTransition( + markerName, + transitions + ) { + if (enableTransitionTracing) { + if (currentPendingTransitionCallbacks === null) { + currentPendingTransitionCallbacks = { + transitionStart: null, + transitionProgress: null, + transitionComplete: null, + markerProgress: null, + markerIncomplete: null, + markerComplete: new Map() + }; + } - if (parentFiber.subtreeFlags & PassiveMask) { - var child = parentFiber.child; + if (currentPendingTransitionCallbacks.markerComplete === null) { + currentPendingTransitionCallbacks.markerComplete = new Map(); + } - while (child !== null) { - setCurrentFiber(child); - commitAtomicPassiveEffects(finishedRoot, child); - child = child.sibling; + currentPendingTransitionCallbacks.markerComplete.set( + markerName, + transitions + ); + } } - } + function addTransitionProgressCallbackToPendingTransition( + transition, + boundaries + ) { + if (enableTransitionTracing) { + if (currentPendingTransitionCallbacks === null) { + currentPendingTransitionCallbacks = { + transitionStart: null, + transitionProgress: new Map(), + transitionComplete: null, + markerProgress: null, + markerIncomplete: null, + markerComplete: null + }; + } - setCurrentFiber(prevDebugFiber); -} + if (currentPendingTransitionCallbacks.transitionProgress === null) { + currentPendingTransitionCallbacks.transitionProgress = new Map(); + } -function commitAtomicPassiveEffects( - finishedRoot, - finishedWork, - committedLanes, - committedTransitions -) { - // "Atomic" effects are ones that need to fire on every commit, even during - // pre-rendering. We call this function when traversing a hidden tree whose - // regular effects are currently disconnected. - var flags = finishedWork.flags; - - switch (finishedWork.tag) { - case OffscreenComponent: { - recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork); - - if (flags & Passive$1) { - // TODO: Pass `current` as argument to this function - var current = finishedWork.alternate; - var instance = finishedWork.stateNode; - commitOffscreenPassiveMountEffects(current, finishedWork, instance); + currentPendingTransitionCallbacks.transitionProgress.set( + transition, + boundaries + ); } - - break; } + function addTransitionCompleteCallbackToPendingTransition(transition) { + if (enableTransitionTracing) { + if (currentPendingTransitionCallbacks === null) { + currentPendingTransitionCallbacks = { + transitionStart: null, + transitionProgress: null, + transitionComplete: [], + markerProgress: null, + markerIncomplete: null, + markerComplete: null + }; + } - case CacheComponent: { - recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork); + if (currentPendingTransitionCallbacks.transitionComplete === null) { + currentPendingTransitionCallbacks.transitionComplete = []; + } - if (flags & Passive$1) { - // TODO: Pass `current` as argument to this function - var _current5 = finishedWork.alternate; - commitCachePassiveMountEffect(_current5, finishedWork); + currentPendingTransitionCallbacks.transitionComplete.push(transition); } - - break; } - default: { - recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork); - break; + function resetRenderTimer() { + workInProgressRootRenderTargetTime = now$1() + RENDER_TIMEOUT_MS; } - } -} -function commitPassiveUnmountEffects(finishedWork) { - setCurrentFiber(finishedWork); - commitPassiveUnmountOnFiber(finishedWork); - resetCurrentFiber(); -} // If we're inside a brand new tree, or a tree that was already visible, then we -// should only suspend host components that have a ShouldSuspendCommit flag. -// Components without it haven't changed since the last commit, so we can skip -// over those. -// -// When we enter a tree that is being revealed (going from hidden -> visible), -// we need to suspend _any_ component that _may_ suspend. Even if they're -// already in the "current" tree. Because their visibility has changed, the -// browser may not have prerendered them yet. So we check the MaySuspendCommit -// flag instead. - -var suspenseyCommitFlag = ShouldSuspendCommit; -function accumulateSuspenseyCommit(finishedWork) { - accumulateSuspenseyCommitOnFiber(finishedWork); -} + function getRenderTargetTime() { + return workInProgressRootRenderTargetTime; + } + var hasUncaughtError = false; + var firstUncaughtError = null; + var legacyErrorBoundariesThatAlreadyFailed = null; // Only used when enableProfilerNestedUpdateScheduledHook is true; + // to track which root is currently committing layout effects. -function recursivelyAccumulateSuspenseyCommit(parentFiber) { - if (parentFiber.subtreeFlags & suspenseyCommitFlag) { - var child = parentFiber.child; + var rootCommittingMutationOrLayoutEffects = null; + var rootDoesHavePassiveEffects = false; + var rootWithPendingPassiveEffects = null; + var pendingPassiveEffectsLanes = NoLanes; + var pendingPassiveProfilerEffects = []; + var pendingPassiveEffectsRemainingLanes = NoLanes; + var pendingPassiveTransitions = null; // Use these to prevent an infinite loop of nested updates - while (child !== null) { - accumulateSuspenseyCommitOnFiber(child); - child = child.sibling; + var NESTED_UPDATE_LIMIT = 50; + var nestedUpdateCount = 0; + var rootWithNestedUpdates = null; + var isFlushingPassiveEffects = false; + var didScheduleUpdateDuringPassiveEffects = false; + var NESTED_PASSIVE_UPDATE_LIMIT = 50; + var nestedPassiveUpdateCount = 0; + var rootWithPassiveNestedUpdates = null; + var isRunningInsertionEffect = false; + function getWorkInProgressRoot() { + return workInProgressRoot; } - } -} + function getWorkInProgressRootRenderLanes() { + return workInProgressRootRenderLanes; + } + function isWorkLoopSuspendedOnData() { + return workInProgressSuspendedReason === SuspendedOnData; + } + function requestUpdateLane(fiber) { + // Special cases + var mode = fiber.mode; -function accumulateSuspenseyCommitOnFiber(fiber) { - switch (fiber.tag) { - case HostHoistable: { - recursivelyAccumulateSuspenseyCommit(fiber); + if ((mode & ConcurrentMode) === NoMode) { + return SyncLane; + } else if ( + (executionContext & RenderContext) !== NoContext && + workInProgressRootRenderLanes !== NoLanes + ) { + // This is a render phase update. These are not officially supported. The + // old behavior is to give this the same "thread" (lanes) as + // whatever is currently rendering. So if you call `setState` on a component + // that happens later in the same render, it will flush. Ideally, we want to + // remove the special case and treat them as if they came from an + // interleaved event. Regardless, this pattern is not officially supported. + // This behavior is only a fallback. The flag only exists until we can roll + // out the setState warning, since existing code might accidentally rely on + // the current behavior. + return pickArbitraryLane(workInProgressRootRenderLanes); + } + + var isTransition = requestCurrentTransition() !== NoTransition; + + if (isTransition) { + if (ReactCurrentBatchConfig.transition !== null) { + var transition = ReactCurrentBatchConfig.transition; + + if (!transition._updatedFibers) { + transition._updatedFibers = new Set(); + } - if (fiber.flags & suspenseyCommitFlag) { - if (fiber.memoizedState !== null) { - suspendResource(); + transition._updatedFibers.add(fiber); } - } - break; - } + var actionScopeLane = peekEntangledActionLane(); + return actionScopeLane !== NoLane // We're inside an async action scope. Reuse the same lane. + ? actionScopeLane // We may or may not be inside an async action scope. If we are, this + : // is the first update in that scope. Either way, we need to get a + // fresh transition lane. + requestTransitionLane(); + } // Updates originating inside certain React methods, like flushSync, have + // their priority set by tracking it with a context variable. + // + // The opaque type returned by the host config is internally a lane, so we can + // use that directly. + // TODO: Move this type conversion to the event priority module. - case HostComponent: { - recursivelyAccumulateSuspenseyCommit(fiber); + var updateLane = getCurrentUpdatePriority(); - break; - } + if (updateLane !== NoLane) { + return updateLane; + } // This update originated outside React. Ask the host environment for an + // appropriate priority, based on the type of event. + // + // The opaque type returned by the host config is internally a lane, so we can + // use that directly. + // TODO: Move this type conversion to the event priority module. + + var eventLane = getCurrentEventPriority(); + return eventLane; + } + + function requestRetryLane(fiber) { + // This is a fork of `requestUpdateLane` designed specifically for Suspense + // "retries" — a special update that attempts to flip a Suspense boundary + // from its placeholder state to its primary/resolved state. + // Special cases + var mode = fiber.mode; + + if ((mode & ConcurrentMode) === NoMode) { + return SyncLane; + } + + return claimNextRetryLane(); + } + + function requestDeferredLane() { + if (workInProgressDeferredLane === NoLane) { + // If there are multiple useDeferredValue hooks in the same render, the + // tasks that they spawn should all be batched together, so they should all + // receive the same lane. + // Check the priority of the current render to decide the priority of the + // deferred task. + // OffscreenLane is used for prerendering, but we also use OffscreenLane + // for incremental hydration. It's given the lowest priority because the + // initial HTML is the same as the final UI. But useDeferredValue during + // hydration is an exception — we need to upgrade the UI to the final + // value. So if we're currently hydrating, we treat it like a transition. + var isPrerendering = + includesSomeLane(workInProgressRootRenderLanes, OffscreenLane) && + !getIsHydrating(); + + if (isPrerendering) { + // There's only one OffscreenLane, so if it contains deferred work, we + // should just reschedule using the same lane. + workInProgressDeferredLane = OffscreenLane; + } else { + // Everything else is spawned as a transition. + workInProgressDeferredLane = requestTransitionLane(); + } + } - case HostRoot: - case HostPortal: { + return workInProgressDeferredLane; + } + function scheduleUpdateOnFiber(root, fiber, lane) { { - recursivelyAccumulateSuspenseyCommit(fiber); + if (isRunningInsertionEffect) { + error("useInsertionEffect must not schedule updates."); + } } - break; - } + { + if (isFlushingPassiveEffects) { + didScheduleUpdateDuringPassiveEffects = true; + } + } // Check if the work loop is currently suspended and waiting for data to + // finish loading. + + if ( + // Suspended render phase + (root === workInProgressRoot && + workInProgressSuspendedReason === SuspendedOnData) || // Suspended commit phase + root.cancelPendingCommit !== null + ) { + // The incoming update might unblock the current render. Interrupt the + // current attempt and restart from the top. + prepareFreshStack(root, NoLanes); + markRootSuspended( + root, + workInProgressRootRenderLanes, + workInProgressDeferredLane + ); + } // Mark that the root has a pending update. - case OffscreenComponent: { - var isHidden = fiber.memoizedState !== null; + markRootUpdated(root, lane); - if (isHidden); - else { - var current = fiber.alternate; - var wasHidden = current !== null && current.memoizedState !== null; - - if (wasHidden) { - // This tree is being revealed. Visit all newly visible suspensey - // instances, even if they're in the current tree. - var prevFlags = suspenseyCommitFlag; - suspenseyCommitFlag = MaySuspendCommit; - recursivelyAccumulateSuspenseyCommit(fiber); - suspenseyCommitFlag = prevFlags; - } else { - recursivelyAccumulateSuspenseyCommit(fiber); + if ( + (executionContext & RenderContext) !== NoLanes && + root === workInProgressRoot + ) { + // This update was dispatched during the render phase. This is a mistake + // if the update originates from user space (with the exception of local + // hook updates, which are handled differently and don't reach this + // function), but there are some internal React features that use this as + // an implementation detail, like selective hydration. + warnAboutRenderPhaseUpdatesInDEV(fiber); // Track lanes that were updated during the render phase + } else { + // This is a normal update, scheduled from outside the render phase. For + // example, during an input event. + { + if (isDevToolsPresent) { + addFiberToLanesMap(root, fiber, lane); + } } - } - break; - } + warnIfUpdatesNotWrappedWithActDEV(fiber); - default: { - recursivelyAccumulateSuspenseyCommit(fiber); - } - } -} + if (enableProfilerNestedUpdateScheduledHook) { + if ( + (executionContext & CommitContext) !== NoContext && + root === rootCommittingMutationOrLayoutEffects + ) { + if (fiber.mode & ProfileMode) { + var current = fiber; + + while (current !== null) { + if (current.tag === Profiler) { + var _current$memoizedProp = current.memoizedProps, + id = _current$memoizedProp.id, + onNestedUpdateScheduled = + _current$memoizedProp.onNestedUpdateScheduled; + + if (typeof onNestedUpdateScheduled === "function") { + onNestedUpdateScheduled(id); + } + } -function detachAlternateSiblings(parentFiber) { - // A fiber was deleted from this parent fiber, but it's still part of the - // previous (alternate) parent fiber's list of children. Because children - // are a linked list, an earlier sibling that's still alive will be - // connected to the deleted fiber via its `alternate`: - // - // live fiber --alternate--> previous live fiber --sibling--> deleted - // fiber - // - // We can't disconnect `alternate` on nodes that haven't been deleted yet, - // but we can disconnect the `sibling` and `child` pointers. - var previousFiber = parentFiber.alternate; - - if (previousFiber !== null) { - var detachedChild = previousFiber.child; - - if (detachedChild !== null) { - previousFiber.child = null; + current = current.return; + } + } + } + } - do { - // $FlowFixMe[incompatible-use] found when upgrading Flow - var detachedSibling = detachedChild.sibling; // $FlowFixMe[incompatible-use] found when upgrading Flow + if (enableTransitionTracing) { + var transition = ReactCurrentBatchConfig.transition; - detachedChild.sibling = null; - detachedChild = detachedSibling; - } while (detachedChild !== null); - } - } -} + if (transition !== null && transition.name != null) { + if (transition.startTime === -1) { + transition.startTime = now$1(); + } -function commitHookPassiveUnmountEffects( - finishedWork, - nearestMountedAncestor, - hookFlags -) { - if (shouldProfile(finishedWork)) { - startPassiveEffectTimer(); - commitHookEffectListUnmount( - hookFlags, - finishedWork, - nearestMountedAncestor - ); - recordPassiveEffectDuration(finishedWork); - } else { - commitHookEffectListUnmount( - hookFlags, - finishedWork, - nearestMountedAncestor - ); - } -} + addTransitionToLanesMap(root, transition, lane); + } + } + + if (root === workInProgressRoot) { + // Received an update to a tree that's in the middle of rendering. Mark + // that there was an interleaved update work on this root. + if ((executionContext & RenderContext) === NoContext) { + workInProgressRootInterleavedUpdatedLanes = mergeLanes( + workInProgressRootInterleavedUpdatedLanes, + lane + ); + } -function recursivelyTraversePassiveUnmountEffects(parentFiber) { - // Deletions effects can be scheduled on any fiber type. They need to happen - // before the children effects have fired. - var deletions = parentFiber.deletions; + if (workInProgressRootExitStatus === RootSuspendedWithDelay) { + // The root already suspended with a delay, which means this render + // definitely won't finish. Since we have a new update, let's mark it as + // suspended now, right before marking the incoming update. This has the + // effect of interrupting the current render and switching to the update. + // TODO: Make sure this doesn't override pings that happen while we've + // already started rendering. + markRootSuspended( + root, + workInProgressRootRenderLanes, + workInProgressDeferredLane + ); + } + } - if ((parentFiber.flags & ChildDeletion) !== NoFlags$1) { - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var childToDelete = deletions[i]; // TODO: Convert this to use recursion + ensureRootIsScheduled(root); - nextEffect = childToDelete; - commitPassiveUnmountEffectsInsideOfDeletedTree_begin( - childToDelete, - parentFiber - ); + if ( + lane === SyncLane && + executionContext === NoContext && + (fiber.mode & ConcurrentMode) === NoMode + ) { + if (ReactCurrentActQueue.isBatchingLegacy); + else { + // Flush the synchronous work now, unless we're already working or inside + // a batch. This is intentionally inside scheduleUpdateOnFiber instead of + // scheduleCallbackForFiber to preserve the ability to schedule a callback + // without immediately flushing it. We only do this for user-initiated + // updates, to preserve historical behavior of legacy mode. + resetRenderTimer(); + flushSyncWorkOnLegacyRootsOnly(); + } + } } } + function isUnsafeClassRenderPhaseUpdate(fiber) { + // Check if this is a render phase update. Only called by class components, + // which special (deprecated) behavior for UNSAFE_componentWillReceive props. + return (executionContext & RenderContext) !== NoContext; + } // This is the entry point for every concurrent task, i.e. anything that + // goes through Scheduler. - detachAlternateSiblings(parentFiber); - } - - var prevDebugFiber = getCurrentFiber(); // TODO: Split PassiveMask into separate masks for mount and unmount? - - if (parentFiber.subtreeFlags & PassiveMask) { - var child = parentFiber.child; + function performConcurrentWorkOnRoot(root, didTimeout) { + { + resetNestedUpdateFlag(); + } - while (child !== null) { - setCurrentFiber(child); - commitPassiveUnmountOnFiber(child); - child = child.sibling; - } - } + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error("Should not already be working."); + } // Flush any pending passive effects before deciding which lanes to work on, + // in case they schedule additional work. - setCurrentFiber(prevDebugFiber); -} + var originalCallbackNode = root.callbackNode; + var didFlushPassiveEffects = flushPassiveEffects(); -function commitPassiveUnmountOnFiber(finishedWork) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - recursivelyTraversePassiveUnmountEffects(finishedWork); + if (didFlushPassiveEffects) { + // Something in the passive effect phase may have canceled the current task. + // Check if the task node for this root was changed. + if (root.callbackNode !== originalCallbackNode) { + // The current task was canceled. Exit. We don't need to call + // `ensureRootIsScheduled` because the check above implies either that + // there's a new task, or that there's no remaining work on this root. + return null; + } + } // Determine the next lanes to work on, using the fields stored + // on the root. + // TODO: This was already computed in the caller. Pass it as an argument. - if (finishedWork.flags & Passive$1) { - commitHookPassiveUnmountEffects( - finishedWork, - finishedWork.return, - Passive | HasEffect - ); - } + var lanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); - break; - } + if (lanes === NoLanes) { + // Defensive coding. This is never expected to happen. + return null; + } // We disable time-slicing in some cases: if the work has been CPU-bound + // for too long ("expired" work, to prevent starvation), or we're in + // sync-updates-by-default mode. + // TODO: We only check `didTimeout` defensively, to account for a Scheduler + // bug we're still investigating. Once the bug in Scheduler is fixed, + // we can remove this, since we track expiration ourselves. + + var shouldTimeSlice = + !includesBlockingLane(root, lanes) && + !includesExpiredLane(root, lanes) && + (disableSchedulerTimeoutInWorkLoop || !didTimeout); + var exitStatus = shouldTimeSlice + ? renderRootConcurrent(root, lanes) + : renderRootSync(root, lanes); + + if (exitStatus !== RootInProgress) { + var renderWasConcurrent = shouldTimeSlice; - case OffscreenComponent: { - var instance = finishedWork.stateNode; - var nextState = finishedWork.memoizedState; - var isHidden = nextState !== null; + do { + if (exitStatus === RootDidNotComplete) { + // The render unwound without completing the tree. This happens in special + // cases where need to exit the current render without producing a + // consistent tree or committing. + markRootSuspended(root, lanes, NoLane); + } else { + // The render completed. + // Check if this render may have yielded to a concurrent event, and if so, + // confirm that any newly rendered stores are consistent. + // TODO: It's possible that even a concurrent render may never have yielded + // to the main thread, if it was fast enough, or if it expired. We could + // skip the consistency check in that case, too. + var finishedWork = root.current.alternate; - if ( - isHidden && - instance._visibility & OffscreenPassiveEffectsConnected && // For backwards compatibility, don't unmount when a tree suspends. In - // the future we may change this to unmount after a delay. - (finishedWork.return === null || - finishedWork.return.tag !== SuspenseComponent) - ) { - // The effects are currently connected. Disconnect them. - // TODO: Add option or heuristic to delay before disconnecting the - // effects. Then if the tree reappears before the delay has elapsed, we - // can skip toggling the effects entirely. - instance._visibility &= ~OffscreenPassiveEffectsConnected; - recursivelyTraverseDisconnectPassiveEffects(finishedWork); - } else { - recursivelyTraversePassiveUnmountEffects(finishedWork); - } + if ( + renderWasConcurrent && + !isRenderConsistentWithExternalStores(finishedWork) + ) { + // A store was mutated in an interleaved event. Render again, + // synchronously, to block further mutations. + exitStatus = renderRootSync(root, lanes); // We assume the tree is now consistent because we didn't yield to any + // concurrent events. - break; - } + renderWasConcurrent = false; // Need to check the exit status again. - default: { - recursivelyTraversePassiveUnmountEffects(finishedWork); - break; - } - } -} + continue; + } // Check if something threw -function recursivelyTraverseDisconnectPassiveEffects(parentFiber) { - // Deletions effects can be scheduled on any fiber type. They need to happen - // before the children effects have fired. - var deletions = parentFiber.deletions; + if (exitStatus === RootErrored) { + var originallyAttemptedLanes = lanes; + var errorRetryLanes = getLanesToRetrySynchronouslyOnError( + root, + originallyAttemptedLanes + ); - if ((parentFiber.flags & ChildDeletion) !== NoFlags$1) { - if (deletions !== null) { - for (var i = 0; i < deletions.length; i++) { - var childToDelete = deletions[i]; // TODO: Convert this to use recursion + if (errorRetryLanes !== NoLanes) { + lanes = errorRetryLanes; + exitStatus = recoverFromConcurrentError( + root, + originallyAttemptedLanes, + errorRetryLanes + ); + renderWasConcurrent = false; + } + } - nextEffect = childToDelete; - commitPassiveUnmountEffectsInsideOfDeletedTree_begin( - childToDelete, - parentFiber - ); - } - } + if (exitStatus === RootFatalErrored) { + var fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended(root, lanes, NoLane); + ensureRootIsScheduled(root); + throw fatalError; + } // We now have a consistent tree. The next step is either to commit it, + // or, if something suspended, wait to commit it after a timeout. + + root.finishedWork = finishedWork; + root.finishedLanes = lanes; + finishConcurrentRender(root, exitStatus, finishedWork, lanes); + } - detachAlternateSiblings(parentFiber); - } + break; + } while (true); + } - var prevDebugFiber = getCurrentFiber(); // TODO: Check PassiveStatic flag + ensureRootIsScheduled(root); + return getContinuationForRoot(root, originalCallbackNode); + } - var child = parentFiber.child; + function recoverFromConcurrentError( + root, + originallyAttemptedLanes, + errorRetryLanes + ) { + // If an error occurred during hydration, discard server response and fall + // back to client side render. + // Before rendering again, save the errors from the previous attempt. + var errorsFromFirstAttempt = workInProgressRootConcurrentErrors; + var wasRootDehydrated = isRootDehydrated(root); + + if (wasRootDehydrated) { + // The shell failed to hydrate. Set a flag to force a client rendering + // during the next attempt. To do this, we call prepareFreshStack now + // to create the root work-in-progress fiber. This is a bit weird in terms + // of factoring, because it relies on renderRootSync not calling + // prepareFreshStack again in the call below, which happens because the + // root and lanes haven't changed. + // + // TODO: I think what we should do is set ForceClientRender inside + // throwException, like we do for nested Suspense boundaries. The reason + // it's here instead is so we can switch to the synchronous work loop, too. + // Something to consider for a future refactor. + var rootWorkInProgress = prepareFreshStack(root, errorRetryLanes); + rootWorkInProgress.flags |= ForceClientRender; - while (child !== null) { - setCurrentFiber(child); - disconnectPassiveEffect(child); - child = child.sibling; - } + { + errorHydratingContainer(); + } + } - setCurrentFiber(prevDebugFiber); -} + var exitStatus = renderRootSync(root, errorRetryLanes); -function disconnectPassiveEffect(finishedWork) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - // TODO: Check PassiveStatic flag - commitHookPassiveUnmountEffects( - finishedWork, - finishedWork.return, - Passive - ); // When disconnecting passive effects, we fire the effects in the same - // order as during a deletiong: parent before child + if (exitStatus !== RootErrored) { + // Successfully finished rendering on retry + if (workInProgressRootDidAttachPingListener && !wasRootDehydrated) { + // During the synchronous render, we attached additional ping listeners. + // This is highly suggestive of an uncached promise (though it's not the + // only reason this would happen). If it was an uncached promise, then + // it may have masked a downstream error from ocurring without actually + // fixing it. Example: + // + // use(Promise.resolve('uncached')) + // throw new Error('Oops!') + // + // When this happens, there's a conflict between blocking potential + // concurrent data races and unwrapping uncached promise values. We + // have to choose one or the other. Because the data race recovery is + // a last ditch effort, we'll disable it. + root.errorRecoveryDisabledLanes = mergeLanes( + root.errorRecoveryDisabledLanes, + originallyAttemptedLanes + ); // Mark the current render as suspended and force it to restart. Once + // these lanes finish successfully, we'll re-enable the error recovery + // mechanism for subsequent updates. - recursivelyTraverseDisconnectPassiveEffects(finishedWork); - break; - } + workInProgressRootInterleavedUpdatedLanes |= originallyAttemptedLanes; + return RootSuspendedWithDelay; + } // The errors from the failed first attempt have been recovered. Add + // them to the collection of recoverable errors. We'll log them in the + // commit phase. - case OffscreenComponent: { - var instance = finishedWork.stateNode; + var errorsFromSecondAttempt = workInProgressRootRecoverableErrors; + workInProgressRootRecoverableErrors = errorsFromFirstAttempt; // The errors from the second attempt should be queued after the errors + // from the first attempt, to preserve the causal sequence. - if (instance._visibility & OffscreenPassiveEffectsConnected) { - instance._visibility &= ~OffscreenPassiveEffectsConnected; - recursivelyTraverseDisconnectPassiveEffects(finishedWork); + if (errorsFromSecondAttempt !== null) { + queueRecoverableErrors(errorsFromSecondAttempt); + } } - break; - } - - default: { - recursivelyTraverseDisconnectPassiveEffects(finishedWork); - break; + return exitStatus; } - } -} -function commitPassiveUnmountEffectsInsideOfDeletedTree_begin( - deletedSubtreeRoot, - nearestMountedAncestor -) { - while (nextEffect !== null) { - var fiber = nextEffect; // Deletion effects fire in parent -> child order - // TODO: Check if fiber has a PassiveStatic flag - - setCurrentFiber(fiber); - commitPassiveUnmountInsideDeletedTreeOnFiber(fiber, nearestMountedAncestor); - resetCurrentFiber(); - var child = fiber.child; // TODO: Only traverse subtree if it has a PassiveStatic flag. - - if (child !== null) { - child.return = fiber; - nextEffect = child; - } else { - commitPassiveUnmountEffectsInsideOfDeletedTree_complete( - deletedSubtreeRoot - ); + function queueRecoverableErrors(errors) { + if (workInProgressRootRecoverableErrors === null) { + workInProgressRootRecoverableErrors = errors; + } else { + // $FlowFixMe[method-unbinding] + workInProgressRootRecoverableErrors.push.apply( + workInProgressRootRecoverableErrors, + errors + ); + } } - } -} -function commitPassiveUnmountEffectsInsideOfDeletedTree_complete( - deletedSubtreeRoot -) { - while (nextEffect !== null) { - var fiber = nextEffect; - var sibling = fiber.sibling; - var returnFiber = fiber.return; // Recursively traverse the entire deleted tree and clean up fiber fields. - // This is more aggressive than ideal, and the long term goal is to only - // have to detach the deleted tree at the root. + function finishConcurrentRender(root, exitStatus, finishedWork, lanes) { + // TODO: The fact that most of these branches are identical suggests that some + // of the exit statuses are not best modeled as exit statuses and should be + // tracked orthogonally. + switch (exitStatus) { + case RootInProgress: + case RootFatalErrored: { + throw new Error("Root did not complete. This is a bug in React."); + } - detachFiberAfterEffects(fiber); + case RootSuspendedWithDelay: { + if (includesOnlyTransitions(lanes)) { + // This is a transition, so we should exit without committing a + // placeholder and without scheduling a timeout. Delay indefinitely + // until we receive more data. + markRootSuspended(root, lanes, workInProgressDeferredLane); + return; + } // Commit the placeholder. - if (fiber === deletedSubtreeRoot) { - nextEffect = null; - return; - } + break; + } - if (sibling !== null) { - sibling.return = returnFiber; - nextEffect = sibling; - return; - } + case RootErrored: + case RootSuspended: + case RootCompleted: { + break; + } - nextEffect = returnFiber; - } -} + default: { + throw new Error("Unknown root exit status."); + } + } -function commitPassiveUnmountInsideDeletedTreeOnFiber( - current, - nearestMountedAncestor -) { - switch (current.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - commitHookPassiveUnmountEffects(current, nearestMountedAncestor, Passive); - break; - } - // TODO: run passive unmount effects when unmounting a root. - // Because passive unmount effects are not currently run, - // the cache instance owned by the root will never be freed. - // When effects are run, the cache should be freed here: - // case HostRoot: { - // if (enableCache) { - // const cache = current.memoizedState.cache; - // releaseCache(cache); - // } - // break; - // } - - case LegacyHiddenComponent: - case OffscreenComponent: { - { + if (shouldForceFlushFallbacksInDEV()) { + // We're inside an `act` scope. Commit immediately. + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + workInProgressDeferredLane + ); + } else { if ( - current.memoizedState !== null && - current.memoizedState.cachePool !== null + includesOnlyRetries(lanes) && + (alwaysThrottleRetries || exitStatus === RootSuspended) ) { - var cache = current.memoizedState.cachePool.pool; // Retain/release the cache used for pending (suspended) nodes. - // Note that this is only reached in the non-suspended/visible case: - // when the content is suspended/hidden, the retain/release occurs - // via the parent Suspense component (see case above). - - if (cache != null) { - retainCache(cache); + // This render only included retries, no updates. Throttle committing + // retries so that we don't show too many loading states too quickly. + var msUntilTimeout = + globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now$1(); // Don't bother with a very short suspense time. + + if (msUntilTimeout > 10) { + markRootSuspended(root, lanes, workInProgressDeferredLane); + var nextLanes = getNextLanes(root, NoLanes); + + if (nextLanes !== NoLanes) { + // There's additional work we can do on this root. We might as well + // attempt to work on that while we're suspended. + return; + } // The render is suspended, it hasn't timed out, and there's no + // lower priority work to do. Instead of committing the fallback + // immediately, wait for more data to arrive. + // TODO: Combine retry throttling with Suspensey commits. Right now they + // run one after the other. + + root.timeoutHandle = scheduleTimeout( + commitRootWhenReady.bind( + null, + root, + finishedWork, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes, + workInProgressDeferredLane + ), + msUntilTimeout + ); + return; } } + + commitRootWhenReady( + root, + finishedWork, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + lanes, + workInProgressDeferredLane + ); } + } + + function commitRootWhenReady( + root, + finishedWork, + recoverableErrors, + transitions, + lanes, + spawnedLane + ) { + // TODO: Combine retry throttling with Suspensey commits. Right now they run + // one after the other. + if (includesOnlyNonUrgentLanes(lanes)) { + // the suspensey resources. The renderer is responsible for accumulating + // all the load events. This all happens in a single synchronous + // transaction, so it track state in its own module scope. + + accumulateSuspenseyCommit(finishedWork); // At the end, ask the renderer if it's ready to commit, or if we should + // suspend. If it's not ready, it will return a callback to subscribe to + // a ready event. + + var schedulePendingCommit = waitForCommitToBeReady(); + + if (schedulePendingCommit !== null) { + // NOTE: waitForCommitToBeReady returns a subscribe function so that we + // only allocate a function if the commit isn't ready yet. The other + // pattern would be to always pass a callback to waitForCommitToBeReady. + // Not yet ready to commit. Delay the commit until the renderer notifies + // us that it's ready. This will be canceled if we start work on the + // root again. + root.cancelPendingCommit = schedulePendingCommit( + commitRoot.bind(null, root, recoverableErrors, transitions) + ); + markRootSuspended(root, lanes, spawnedLane); + return; + } + } // Otherwise, commit immediately. - break; + commitRoot(root, recoverableErrors, transitions, spawnedLane); } - case SuspenseComponent: { - if (enableTransitionTracing) { - // We need to mark this fiber's parents as deleted - var offscreenFiber = current.child; - var instance = offscreenFiber.stateNode; - var transitions = instance._transitions; + function isRenderConsistentWithExternalStores(finishedWork) { + // Search the rendered tree for external store reads, and check whether the + // stores were mutated in a concurrent event. Intentionally using an iterative + // loop instead of recursion so we can exit early. + var node = finishedWork; - if (transitions !== null) { - var abortReason = { - reason: "suspense", - name: current.memoizedProps.unstable_name || null - }; + while (true) { + if (node.flags & StoreConsistency) { + var updateQueue = node.updateQueue; - if ( - current.memoizedState === null || - current.memoizedState.dehydrated === null - ) { - abortParentMarkerTransitionsForDeletedFiber( - offscreenFiber, - abortReason, - transitions, - instance, - true - ); + if (updateQueue !== null) { + var checks = updateQueue.stores; - if (nearestMountedAncestor !== null) { - abortParentMarkerTransitionsForDeletedFiber( - nearestMountedAncestor, - abortReason, - transitions, - instance, - false - ); + if (checks !== null) { + for (var i = 0; i < checks.length; i++) { + var check = checks[i]; + var getSnapshot = check.getSnapshot; + var renderedValue = check.value; + + try { + if (!objectIs(getSnapshot(), renderedValue)) { + // Found an inconsistent store. + return false; + } + } catch (error) { + // If `getSnapshot` throws, return `false`. This will schedule + // a re-render, and the error will be rethrown during render. + return false; + } + } } } } - } - - break; - } - case CacheComponent: { - { - var _cache = current.memoizedState.cache; - releaseCache(_cache); - } + var child = node.child; - break; - } + if (node.subtreeFlags & StoreConsistency && child !== null) { + child.return = node; + node = child; + continue; + } - case TracingMarkerComponent: { - if (enableTransitionTracing) { - // We need to mark this fiber's parents as deleted - var _instance5 = current.stateNode; - var _transitions = _instance5.transitions; - - if (_transitions !== null) { - var _abortReason = { - reason: "marker", - name: current.memoizedProps.name - }; - abortParentMarkerTransitionsForDeletedFiber( - current, - _abortReason, - _transitions, - null, - true - ); + if (node === finishedWork) { + return true; + } - if (nearestMountedAncestor !== null) { - abortParentMarkerTransitionsForDeletedFiber( - nearestMountedAncestor, - _abortReason, - _transitions, - null, - false - ); + while (node.sibling === null) { + if (node.return === null || node.return === finishedWork) { + return true; } + + node = node.return; } - } - break; + node.sibling.return = node.return; + node = node.sibling; + } // Flow doesn't know this is unreachable, but eslint does + // eslint-disable-next-line no-unreachable + + return true; } - } -} -function invokeLayoutEffectMountInDEV(fiber) { - { - // We don't need to re-check StrictEffectsMode here. - // This function is only called if that check has already passed. - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - try { - commitHookEffectListMount(Layout | HasEffect, fiber); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } + function markRootSuspended(root, suspendedLanes, spawnedLane) { + // When suspending, we should always exclude lanes that were pinged or (more + // rarely, since we try to avoid it) updated during the render phase. + // TODO: Lol maybe there's a better way to factor this besides this + // obnoxiously named function :) + suspendedLanes = removeLanes( + suspendedLanes, + workInProgressRootPingedLanes + ); + suspendedLanes = removeLanes( + suspendedLanes, + workInProgressRootInterleavedUpdatedLanes + ); + markRootSuspended$1(root, suspendedLanes, spawnedLane); + } // This is the entry point for synchronous tasks that don't go + // through Scheduler - break; + function performSyncWorkOnRoot(root, lanes) { + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error("Should not already be working."); } - case ClassComponent: { - var instance = fiber.stateNode; + var didFlushPassiveEffects = flushPassiveEffects(); - if (typeof instance.componentDidMount === "function") { - try { - instance.componentDidMount(); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } - } + if (didFlushPassiveEffects) { + // If passive effects were flushed, exit to the outer work loop in the root + // scheduler, so we can recompute the priority. + // TODO: We don't actually need this `ensureRootIsScheduled` call because + // this path is only reachable if the root is already part of the schedule. + // I'm including it only for consistency with the other exit points from + // this function. Can address in a subsequent refactor. + ensureRootIsScheduled(root); + return null; + } - break; + { + syncNestedUpdateFlag(); } - } - } -} -function invokePassiveEffectMountInDEV(fiber) { - { - // We don't need to re-check StrictEffectsMode here. - // This function is only called if that check has already passed. - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - try { - commitHookEffectListMount(Passive | HasEffect, fiber); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } + var exitStatus = renderRootSync(root, lanes); - break; - } - } - } -} + if (root.tag !== LegacyRoot && exitStatus === RootErrored) { + // If something threw an error, try rendering one more time. We'll render + // synchronously to block concurrent data mutations, and we'll includes + // all pending updates are included. If it still fails after the second + // attempt, we'll give up and commit the resulting tree. + var originallyAttemptedLanes = lanes; + var errorRetryLanes = getLanesToRetrySynchronouslyOnError( + root, + originallyAttemptedLanes + ); -function invokeLayoutEffectUnmountInDEV(fiber) { - { - // We don't need to re-check StrictEffectsMode here. - // This function is only called if that check has already passed. - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - try { - commitHookEffectListUnmount(Layout | HasEffect, fiber, fiber.return); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); + if (errorRetryLanes !== NoLanes) { + lanes = errorRetryLanes; + exitStatus = recoverFromConcurrentError( + root, + originallyAttemptedLanes, + errorRetryLanes + ); } + } - break; + if (exitStatus === RootFatalErrored) { + var fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended(root, lanes, NoLane); + ensureRootIsScheduled(root); + throw fatalError; } - case ClassComponent: { - var instance = fiber.stateNode; + if (exitStatus === RootDidNotComplete) { + // The render unwound without completing the tree. This happens in special + // cases where need to exit the current render without producing a + // consistent tree or committing. + markRootSuspended(root, lanes, NoLane); + ensureRootIsScheduled(root); + return null; + } // We now have a consistent tree. Because this is a sync render, we + // will commit it even if something suspended. - if (typeof instance.componentWillUnmount === "function") { - safelyCallComponentWillUnmount(fiber, fiber.return, instance); - } + var finishedWork = root.current.alternate; + root.finishedWork = finishedWork; + root.finishedLanes = lanes; + commitRoot( + root, + workInProgressRootRecoverableErrors, + workInProgressTransitions, + workInProgressDeferredLane + ); // Before exiting, make sure there's a callback scheduled for the next + // pending level. - break; - } + ensureRootIsScheduled(root); + return null; } - } -} + function getExecutionContext() { + return executionContext; + } + // Warning, this opts-out of checking the function body. + // eslint-disable-next-line no-unused-vars + // eslint-disable-next-line no-redeclare + // eslint-disable-next-line no-redeclare -function invokePassiveEffectUnmountInDEV(fiber) { - { - // We don't need to re-check StrictEffectsMode here. - // This function is only called if that check has already passed. - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - try { - commitHookEffectListUnmount(Passive | HasEffect, fiber, fiber.return); - } catch (error) { - captureCommitPhaseError(fiber, fiber.return, error); - } + function flushSync(fn) { + // In legacy mode, we flush pending passive effects at the beginning of the + // next event, not at the end of the previous one. + if ( + rootWithPendingPassiveEffects !== null && + rootWithPendingPassiveEffects.tag === LegacyRoot && + (executionContext & (RenderContext | CommitContext)) === NoContext + ) { + flushPassiveEffects(); } - } - } -} -function getCacheSignal() { - var cache = readContext(CacheContext); - return cache.controller.signal; -} + var prevExecutionContext = executionContext; + executionContext |= BatchedContext; + var prevTransition = ReactCurrentBatchConfig.transition; + var previousPriority = getCurrentUpdatePriority(); -function getCacheForType(resourceType) { - var cache = readContext(CacheContext); - var cacheForType = cache.data.get(resourceType); + try { + ReactCurrentBatchConfig.transition = null; + setCurrentUpdatePriority(DiscreteEventPriority); - if (cacheForType === undefined) { - cacheForType = resourceType(); - cache.data.set(resourceType, cacheForType); - } + if (fn) { + return fn(); + } else { + return undefined; + } + } finally { + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig.transition = prevTransition; + executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. + // Note that this will happen even if batchedUpdates is higher up + // the stack. - return cacheForType; -} + if ( + (executionContext & (RenderContext | CommitContext)) === + NoContext + ) { + flushSyncWorkOnAllRoots(); + } + } + } + function isInvalidExecutionContextForEventFunction() { + // Used to throw if certain APIs are called from the wrong context. + return (executionContext & RenderContext) !== NoContext; + } // This is called by the HiddenContext module when we enter or leave a + // hidden subtree. The stack logic is managed there because that's the only + // place that ever modifies it. Which module it lives in doesn't matter for + // performance because this function will get inlined regardless -var DefaultCacheDispatcher = { - getCacheSignal: getCacheSignal, - getCacheForType: getCacheForType -}; - -if (typeof Symbol === "function" && Symbol.for) { - var symbolFor = Symbol.for; - symbolFor("selector.component"); - symbolFor("selector.has_pseudo_class"); - symbolFor("selector.role"); - symbolFor("selector.test_id"); - symbolFor("selector.text"); -} + function setEntangledRenderLanes(newEntangledRenderLanes) { + entangledRenderLanes = newEntangledRenderLanes; + } + function getEntangledRenderLanes() { + return entangledRenderLanes; + } -var ReactCurrentActQueue$1 = ReactSharedInternals.ReactCurrentActQueue; -function isLegacyActEnvironment(fiber) { - { - // Legacy mode. We preserve the behavior of React 17's act. It assumes an - // act environment whenever `jest` is defined, but you can still turn off - // spurious warnings by setting IS_REACT_ACT_ENVIRONMENT explicitly - // to false. - // $FlowFixMe[cannot-resolve-name] Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global - typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" // $FlowFixMe[cannot-resolve-name] - ? IS_REACT_ACT_ENVIRONMENT - : undefined; // $FlowFixMe[cannot-resolve-name] - Flow doesn't know about jest - return warnsIfNotActing; - } -} -function isConcurrentActEnvironment() { - { - var isReactActEnvironmentGlobal = // $FlowFixMe[cannot-resolve-name] Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global - typeof IS_REACT_ACT_ENVIRONMENT !== "undefined" // $FlowFixMe[cannot-resolve-name] - ? IS_REACT_ACT_ENVIRONMENT - : undefined; + function resetWorkInProgressStack() { + if (workInProgress === null) return; + var interruptedWork; - if ( - !isReactActEnvironmentGlobal && - ReactCurrentActQueue$1.current !== null - ) { - // TODO: Include link to relevant documentation page. - error( - "The current testing environment is not configured to support " + - "act(...)" - ); - } + if (workInProgressSuspendedReason === NotSuspended) { + // Normal case. Work-in-progress hasn't started yet. Unwind all + // its parents. + interruptedWork = workInProgress.return; + } else { + // Work-in-progress is in suspended state. Reset the work loop and unwind + // both the suspended fiber and all its parents. + resetSuspendedWorkLoopOnUnwind(workInProgress); + interruptedWork = workInProgress; + } - return isReactActEnvironmentGlobal; - } -} + while (interruptedWork !== null) { + var current = interruptedWork.alternate; + unwindInterruptedWork(current, interruptedWork); + interruptedWork = interruptedWork.return; + } -var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; -var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, - ReactCurrentCache = ReactSharedInternals.ReactCurrentCache, - ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner, - ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig, - ReactCurrentActQueue = ReactSharedInternals.ReactCurrentActQueue; -var NoContext = - /* */ - 0; -var BatchedContext = - /* */ - 1; -var RenderContext = - /* */ - 2; -var CommitContext = - /* */ - 4; -var RootInProgress = 0; -var RootFatalErrored = 1; -var RootErrored = 2; -var RootSuspended = 3; -var RootSuspendedWithDelay = 4; -var RootCompleted = 5; -var RootDidNotComplete = 6; // Describes where we are in the React execution stack - -var executionContext = NoContext; // The root we're working on - -var workInProgressRoot = null; // The fiber we're working on - -var workInProgress = null; // The lanes we're rendering - -var workInProgressRootRenderLanes = NoLanes; -var NotSuspended = 0; -var SuspendedOnError = 1; -var SuspendedOnData = 2; -var SuspendedOnImmediate = 3; -var SuspendedOnInstance = 4; -var SuspendedOnInstanceAndReadyToContinue = 5; -var SuspendedOnDeprecatedThrowPromise = 6; -var SuspendedAndReadyToContinue = 7; -var SuspendedOnHydration = 8; // When this is true, the work-in-progress fiber just suspended (or errored) and -// we've yet to unwind the stack. In some cases, we may yield to the main thread -// after this happens. If the fiber is pinged before we resume, we can retry -// immediately instead of unwinding the stack. - -var workInProgressSuspendedReason = NotSuspended; -var workInProgressThrownValue = null; // Whether a ping listener was attached during this render. This is slightly -// different that whether something suspended, because we don't add multiple -// listeners to a promise we've already seen (per root and lane). - -var workInProgressRootDidAttachPingListener = false; // A contextual version of workInProgressRootRenderLanes. It is a superset of -// the lanes that we started working on at the root. When we enter a subtree -// that is currently hidden, we add the lanes that would have committed if -// the hidden tree hadn't been deferred. This is modified by the -// HiddenContext module. -// -// Most things in the work loop should deal with workInProgressRootRenderLanes. -// Most things in begin/complete phases should deal with entangledRenderLanes. - -var entangledRenderLanes = NoLanes; // Whether to root completed, errored, suspended, etc. - -var workInProgressRootExitStatus = RootInProgress; // A fatal error, if one is thrown - -var workInProgressRootFatalError = null; // The work left over by components that were visited during this render. Only -// includes unprocessed updates, not work in bailed out children. - -var workInProgressRootSkippedLanes = NoLanes; // Lanes that were updated (in an interleaved event) during this render. - -var workInProgressRootInterleavedUpdatedLanes = NoLanes; // Lanes that were updated during the render phase (*not* an interleaved event). - -var workInProgressRootPingedLanes = NoLanes; // If this lane scheduled deferred work, this is the lane of the deferred task. - -var workInProgressDeferredLane = NoLane; // Errors that are thrown during the render phase. - -var workInProgressRootConcurrentErrors = null; // These are errors that we recovered from without surfacing them to the UI. -// We will log them once the tree commits. - -var workInProgressRootRecoverableErrors = null; // The most recent time we either committed a fallback, or when a fallback was -// filled in with the resolved UI. This lets us throttle the appearance of new -// content as it streams in, to minimize jank. -// TODO: Think of a better name for this variable? - -var globalMostRecentFallbackTime = 0; -var FALLBACK_THROTTLE_MS = 300; // The absolute time for when we should start giving up on rendering -// more and prefer CPU suspense heuristics instead. - -var workInProgressRootRenderTargetTime = Infinity; // How long a render is supposed to take before we start following CPU -// suspense heuristics and opt out of rendering more content. - -var RENDER_TIMEOUT_MS = 500; -var workInProgressTransitions = null; -function getWorkInProgressTransitions() { - return workInProgressTransitions; -} -var currentPendingTransitionCallbacks = null; -var currentEndTime = null; -function addTransitionStartCallbackToPendingTransition(transition) { - if (enableTransitionTracing) { - if (currentPendingTransitionCallbacks === null) { - currentPendingTransitionCallbacks = { - transitionStart: [], - transitionProgress: null, - transitionComplete: null, - markerProgress: null, - markerIncomplete: null, - markerComplete: null - }; + workInProgress = null; } - if (currentPendingTransitionCallbacks.transitionStart === null) { - currentPendingTransitionCallbacks.transitionStart = []; - } + function prepareFreshStack(root, lanes) { + root.finishedWork = null; + root.finishedLanes = NoLanes; + var timeoutHandle = root.timeoutHandle; - currentPendingTransitionCallbacks.transitionStart.push(transition); - } -} -function addMarkerProgressCallbackToPendingTransition( - markerName, - transitions, - pendingBoundaries -) { - if (enableTransitionTracing) { - if (currentPendingTransitionCallbacks === null) { - currentPendingTransitionCallbacks = { - transitionStart: null, - transitionProgress: null, - transitionComplete: null, - markerProgress: new Map(), - markerIncomplete: null, - markerComplete: null - }; - } + if (timeoutHandle !== noTimeout) { + // The root previous suspended and scheduled a timeout to commit a fallback + // state. Now that we have additional work, cancel the timeout. + root.timeoutHandle = noTimeout; // $FlowFixMe[incompatible-call] Complains noTimeout is not a TimeoutID, despite the check above - if (currentPendingTransitionCallbacks.markerProgress === null) { - currentPendingTransitionCallbacks.markerProgress = new Map(); - } + cancelTimeout(timeoutHandle); + } - currentPendingTransitionCallbacks.markerProgress.set(markerName, { - pendingBoundaries: pendingBoundaries, - transitions: transitions - }); - } -} -function addMarkerIncompleteCallbackToPendingTransition( - markerName, - transitions, - aborts -) { - if (enableTransitionTracing) { - if (currentPendingTransitionCallbacks === null) { - currentPendingTransitionCallbacks = { - transitionStart: null, - transitionProgress: null, - transitionComplete: null, - markerProgress: null, - markerIncomplete: new Map(), - markerComplete: null - }; - } + var cancelPendingCommit = root.cancelPendingCommit; - if (currentPendingTransitionCallbacks.markerIncomplete === null) { - currentPendingTransitionCallbacks.markerIncomplete = new Map(); - } + if (cancelPendingCommit !== null) { + root.cancelPendingCommit = null; + cancelPendingCommit(); + } - currentPendingTransitionCallbacks.markerIncomplete.set(markerName, { - transitions: transitions, - aborts: aborts - }); - } -} -function addMarkerCompleteCallbackToPendingTransition(markerName, transitions) { - if (enableTransitionTracing) { - if (currentPendingTransitionCallbacks === null) { - currentPendingTransitionCallbacks = { - transitionStart: null, - transitionProgress: null, - transitionComplete: null, - markerProgress: null, - markerIncomplete: null, - markerComplete: new Map() - }; - } + resetWorkInProgressStack(); + workInProgressRoot = root; + var rootWorkInProgress = createWorkInProgress(root.current, null); + workInProgress = rootWorkInProgress; + workInProgressRootRenderLanes = lanes; + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + workInProgressRootDidAttachPingListener = false; + workInProgressRootExitStatus = RootInProgress; + workInProgressRootFatalError = null; + workInProgressRootSkippedLanes = NoLanes; + workInProgressRootInterleavedUpdatedLanes = NoLanes; + workInProgressRootPingedLanes = NoLanes; + workInProgressDeferredLane = NoLane; + workInProgressRootConcurrentErrors = null; + workInProgressRootRecoverableErrors = null; // Get the lanes that are entangled with whatever we're about to render. We + // track these separately so we can distinguish the priority of the render + // task from the priority of the lanes it is entangled with. For example, a + // transition may not be allowed to finish unless it includes the Sync lane, + // which is currently suspended. We should be able to render the Transition + // and Sync lane in the same batch, but at Transition priority, because the + // Sync lane already suspended. - if (currentPendingTransitionCallbacks.markerComplete === null) { - currentPendingTransitionCallbacks.markerComplete = new Map(); - } + entangledRenderLanes = getEntangledLanes(root, lanes); + finishQueueingConcurrentUpdates(); - currentPendingTransitionCallbacks.markerComplete.set( - markerName, - transitions - ); - } -} -function addTransitionProgressCallbackToPendingTransition( - transition, - boundaries -) { - if (enableTransitionTracing) { - if (currentPendingTransitionCallbacks === null) { - currentPendingTransitionCallbacks = { - transitionStart: null, - transitionProgress: new Map(), - transitionComplete: null, - markerProgress: null, - markerIncomplete: null, - markerComplete: null - }; - } + { + ReactStrictModeWarnings.discardPendingWarnings(); + } - if (currentPendingTransitionCallbacks.transitionProgress === null) { - currentPendingTransitionCallbacks.transitionProgress = new Map(); + return rootWorkInProgress; } - currentPendingTransitionCallbacks.transitionProgress.set( - transition, - boundaries - ); - } -} -function addTransitionCompleteCallbackToPendingTransition(transition) { - if (enableTransitionTracing) { - if (currentPendingTransitionCallbacks === null) { - currentPendingTransitionCallbacks = { - transitionStart: null, - transitionProgress: null, - transitionComplete: [], - markerProgress: null, - markerIncomplete: null, - markerComplete: null - }; + function resetSuspendedWorkLoopOnUnwind(fiber) { + // Reset module-level state that was set during the render phase. + resetContextDependencies(); + resetHooksOnUnwind(fiber); + resetChildReconcilerOnUnwind(); } - if (currentPendingTransitionCallbacks.transitionComplete === null) { - currentPendingTransitionCallbacks.transitionComplete = []; - } + function handleThrow(root, thrownValue) { + // A component threw an exception. Usually this is because it suspended, but + // it also includes regular program errors. + // + // We're either going to unwind the stack to show a Suspense or error + // boundary, or we're going to replay the component again. Like after a + // promise resolves. + // + // Until we decide whether we're going to unwind or replay, we should preserve + // the current state of the work loop without resetting anything. + // + // If we do decide to unwind the stack, module-level variables will be reset + // in resetSuspendedWorkLoopOnUnwind. + // These should be reset immediately because they're only supposed to be set + // when React is executing user code. + resetHooksAfterThrow(); + resetCurrentFiber(); + ReactCurrentOwner.current = null; + + if (thrownValue === SuspenseException) { + // This is a special type of exception used for Suspense. For historical + // reasons, the rest of the Suspense implementation expects the thrown value + // to be a thenable, because before `use` existed that was the (unstable) + // API for suspending. This implementation detail can change later, once we + // deprecate the old API in favor of `use`. + thrownValue = getSuspendedThenable(); + workInProgressSuspendedReason = + shouldRemainOnPreviousScreen() && // Check if there are other pending updates that might possibly unblock this + // component from suspending. This mirrors the check in + // renderDidSuspendDelayIfPossible. We should attempt to unify them somehow. + // TODO: Consider unwinding immediately, using the + // SuspendedOnHydration mechanism. + !includesNonIdleWork(workInProgressRootSkippedLanes) && + !includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes) // Suspend work loop until data resolves + ? SuspendedOnData // Don't suspend work loop, except to check if the data has + : // immediately resolved (i.e. in a microtask). Otherwise, trigger the + // nearest Suspense fallback. + SuspendedOnImmediate; + } else if (thrownValue === SuspenseyCommitException) { + thrownValue = getSuspendedThenable(); + workInProgressSuspendedReason = SuspendedOnInstance; + } else if (thrownValue === SelectiveHydrationException) { + // An update flowed into a dehydrated boundary. Before we can apply the + // update, we need to finish hydrating. Interrupt the work-in-progress + // render so we can restart at the hydration lane. + // + // The ideal implementation would be able to switch contexts without + // unwinding the current stack. + // + // We could name this something more general but as of now it's the only + // case where we think this should happen. + workInProgressSuspendedReason = SuspendedOnHydration; + } else { + // This is a regular error. + var isWakeable = + thrownValue !== null && + typeof thrownValue === "object" && + typeof thrownValue.then === "function"; + workInProgressSuspendedReason = isWakeable // A wakeable object was thrown by a legacy Suspense implementation. + ? // This has slightly different behavior than suspending with `use`. + SuspendedOnDeprecatedThrowPromise // This is a regular error. If something earlier in the component already + : // suspended, we must clear the thenable state to unblock the work loop. + SuspendedOnError; + } + + workInProgressThrownValue = thrownValue; + var erroredWork = workInProgress; + + if (erroredWork === null) { + // This is a fatal error + workInProgressRootExitStatus = RootFatalErrored; + workInProgressRootFatalError = thrownValue; + return; + } - currentPendingTransitionCallbacks.transitionComplete.push(transition); - } -} + if (erroredWork.mode & ProfileMode) { + // Record the time spent rendering before an error was thrown. This + // avoids inaccurate Profiler durations in the case of a + // suspended render. + stopProfilerTimerIfRunningAndRecordDelta(erroredWork, true); + } -function resetRenderTimer() { - workInProgressRootRenderTargetTime = now$1() + RENDER_TIMEOUT_MS; -} + if (enableSchedulingProfiler) { + markComponentRenderStopped(); -function getRenderTargetTime() { - return workInProgressRootRenderTargetTime; -} -var hasUncaughtError = false; -var firstUncaughtError = null; -var legacyErrorBoundariesThatAlreadyFailed = null; // Only used when enableProfilerNestedUpdateScheduledHook is true; -// to track which root is currently committing layout effects. - -var rootCommittingMutationOrLayoutEffects = null; -var rootDoesHavePassiveEffects = false; -var rootWithPendingPassiveEffects = null; -var pendingPassiveEffectsLanes = NoLanes; -var pendingPassiveProfilerEffects = []; -var pendingPassiveEffectsRemainingLanes = NoLanes; -var pendingPassiveTransitions = null; // Use these to prevent an infinite loop of nested updates - -var NESTED_UPDATE_LIMIT = 50; -var nestedUpdateCount = 0; -var rootWithNestedUpdates = null; -var isFlushingPassiveEffects = false; -var didScheduleUpdateDuringPassiveEffects = false; -var NESTED_PASSIVE_UPDATE_LIMIT = 50; -var nestedPassiveUpdateCount = 0; -var rootWithPassiveNestedUpdates = null; -var isRunningInsertionEffect = false; -function getWorkInProgressRoot() { - return workInProgressRoot; -} -function getWorkInProgressRootRenderLanes() { - return workInProgressRootRenderLanes; -} -function isWorkLoopSuspendedOnData() { - return workInProgressSuspendedReason === SuspendedOnData; -} -function requestUpdateLane(fiber) { - // Special cases - var mode = fiber.mode; - - if ((mode & ConcurrentMode) === NoMode) { - return SyncLane; - } else if ( - (executionContext & RenderContext) !== NoContext && - workInProgressRootRenderLanes !== NoLanes - ) { - // This is a render phase update. These are not officially supported. The - // old behavior is to give this the same "thread" (lanes) as - // whatever is currently rendering. So if you call `setState` on a component - // that happens later in the same render, it will flush. Ideally, we want to - // remove the special case and treat them as if they came from an - // interleaved event. Regardless, this pattern is not officially supported. - // This behavior is only a fallback. The flag only exists until we can roll - // out the setState warning, since existing code might accidentally rely on - // the current behavior. - return pickArbitraryLane(workInProgressRootRenderLanes); - } - - var isTransition = requestCurrentTransition() !== NoTransition; - - if (isTransition) { - if (ReactCurrentBatchConfig.transition !== null) { - var transition = ReactCurrentBatchConfig.transition; - - if (!transition._updatedFibers) { - transition._updatedFibers = new Set(); - } - - transition._updatedFibers.add(fiber); - } - - var actionScopeLane = peekEntangledActionLane(); - return actionScopeLane !== NoLane // We're inside an async action scope. Reuse the same lane. - ? actionScopeLane // We may or may not be inside an async action scope. If we are, this - : // is the first update in that scope. Either way, we need to get a - // fresh transition lane. - requestTransitionLane(); - } // Updates originating inside certain React methods, like flushSync, have - // their priority set by tracking it with a context variable. - // - // The opaque type returned by the host config is internally a lane, so we can - // use that directly. - // TODO: Move this type conversion to the event priority module. - - var updateLane = getCurrentUpdatePriority(); - - if (updateLane !== NoLane) { - return updateLane; - } // This update originated outside React. Ask the host environment for an - // appropriate priority, based on the type of event. - // - // The opaque type returned by the host config is internally a lane, so we can - // use that directly. - // TODO: Move this type conversion to the event priority module. - - var eventLane = getCurrentEventPriority(); - return eventLane; -} + switch (workInProgressSuspendedReason) { + case SuspendedOnError: { + markComponentErrored( + erroredWork, + thrownValue, + workInProgressRootRenderLanes + ); + break; + } + + case SuspendedOnData: + case SuspendedOnImmediate: + case SuspendedOnDeprecatedThrowPromise: + case SuspendedAndReadyToContinue: { + var wakeable = thrownValue; + markComponentSuspended( + erroredWork, + wakeable, + workInProgressRootRenderLanes + ); + break; + } + } + } + } -function requestRetryLane(fiber) { - // This is a fork of `requestUpdateLane` designed specifically for Suspense - // "retries" — a special update that attempts to flip a Suspense boundary - // from its placeholder state to its primary/resolved state. - // Special cases - var mode = fiber.mode; + function shouldRemainOnPreviousScreen() { + // This is asking whether it's better to suspend the transition and remain + // on the previous screen, versus showing a fallback as soon as possible. It + // takes into account both the priority of render and also whether showing a + // fallback would produce a desirable user experience. + var handler = getSuspenseHandler(); - if ((mode & ConcurrentMode) === NoMode) { - return SyncLane; - } + if (handler === null) { + // There's no Suspense boundary that can provide a fallback. We have no + // choice but to remain on the previous screen. + // NOTE: We do this even for sync updates, for lack of any better option. In + // the future, we may change how we handle this, like by putting the whole + // root into a "detached" mode. + return true; + } // TODO: Once `use` has fully replaced the `throw promise` pattern, we should + // be able to remove the equivalent check in finishConcurrentRender, and rely + // just on this one. + + if (includesOnlyTransitions(workInProgressRootRenderLanes)) { + if (getShellBoundary() === null) { + // We're rendering inside the "shell" of the app. Activating the nearest + // fallback would cause visible content to disappear. It's better to + // suspend the transition and remain on the previous screen. + return true; + } else { + // We're rendering content that wasn't part of the previous screen. + // Rather than block the transition, it's better to show a fallback as + // soon as possible. The appearance of any nested fallbacks will be + // throttled to avoid jank. + return false; + } + } - return claimNextRetryLane(); -} + if ( + includesOnlyRetries(workInProgressRootRenderLanes) || // In this context, an OffscreenLane counts as a Retry + // TODO: It's become increasingly clear that Retries and Offscreen are + // deeply connected. They probably can be unified further. + includesSomeLane(workInProgressRootRenderLanes, OffscreenLane) + ) { + // During a retry, we can suspend rendering if the nearest Suspense boundary + // is the boundary of the "shell", because we're guaranteed not to block + // any new content from appearing. + // + // The reason we must check if this is a retry is because it guarantees + // that suspending the work loop won't block an actual update, because + // retries don't "update" anything; they fill in fallbacks that were left + // behind by a previous transition. + return handler === getShellBoundary(); + } // For all other Lanes besides Transitions and Retries, we should not wait + // for the data to load. -function requestDeferredLane() { - if (workInProgressDeferredLane === NoLane) { - // If there are multiple useDeferredValue hooks in the same render, the - // tasks that they spawn should all be batched together, so they should all - // receive the same lane. - // Check the priority of the current render to decide the priority of the - // deferred task. - // OffscreenLane is used for prerendering, but we also use OffscreenLane - // for incremental hydration. It's given the lowest priority because the - // initial HTML is the same as the final UI. But useDeferredValue during - // hydration is an exception — we need to upgrade the UI to the final - // value. So if we're currently hydrating, we treat it like a transition. - var isPrerendering = - includesSomeLane(workInProgressRootRenderLanes, OffscreenLane) && - !getIsHydrating(); - - if (isPrerendering) { - // There's only one OffscreenLane, so if it contains deferred work, we - // should just reschedule using the same lane. - workInProgressDeferredLane = OffscreenLane; - } else { - // Everything else is spawned as a transition. - workInProgressDeferredLane = requestTransitionLane(); + return false; } - } - return workInProgressDeferredLane; -} -function scheduleUpdateOnFiber(root, fiber, lane) { - { - if (isRunningInsertionEffect) { - error("useInsertionEffect must not schedule updates."); - } - } - - { - if (isFlushingPassiveEffects) { - didScheduleUpdateDuringPassiveEffects = true; - } - } // Check if the work loop is currently suspended and waiting for data to - // finish loading. - - if ( - // Suspended render phase - (root === workInProgressRoot && - workInProgressSuspendedReason === SuspendedOnData) || // Suspended commit phase - root.cancelPendingCommit !== null - ) { - // The incoming update might unblock the current render. Interrupt the - // current attempt and restart from the top. - prepareFreshStack(root, NoLanes); - markRootSuspended( - root, - workInProgressRootRenderLanes, - workInProgressDeferredLane - ); - } // Mark that the root has a pending update. - - markRootUpdated(root, lane); - - if ( - (executionContext & RenderContext) !== NoLanes && - root === workInProgressRoot - ) { - // This update was dispatched during the render phase. This is a mistake - // if the update originates from user space (with the exception of local - // hook updates, which are handled differently and don't reach this - // function), but there are some internal React features that use this as - // an implementation detail, like selective hydration. - warnAboutRenderPhaseUpdatesInDEV(fiber); // Track lanes that were updated during the render phase - } else { - // This is a normal update, scheduled from outside the render phase. For - // example, during an input event. - { - if (isDevToolsPresent) { - addFiberToLanesMap(root, fiber, lane); + function pushDispatcher(container) { + var prevDispatcher = ReactCurrentDispatcher.current; + ReactCurrentDispatcher.current = ContextOnlyDispatcher; + + if (prevDispatcher === null) { + // The React isomorphic package does not include a default dispatcher. + // Instead the first renderer will lazily attach one, in order to give + // nicer error messages. + return ContextOnlyDispatcher; + } else { + return prevDispatcher; } } - warnIfUpdatesNotWrappedWithActDEV(fiber); - - if (enableProfilerNestedUpdateScheduledHook) { - if ( - (executionContext & CommitContext) !== NoContext && - root === rootCommittingMutationOrLayoutEffects - ) { - if (fiber.mode & ProfileMode) { - var current = fiber; - - while (current !== null) { - if (current.tag === Profiler) { - var _current$memoizedProp = current.memoizedProps, - id = _current$memoizedProp.id, - onNestedUpdateScheduled = - _current$memoizedProp.onNestedUpdateScheduled; - - if (typeof onNestedUpdateScheduled === "function") { - onNestedUpdateScheduled(id); - } - } + function popDispatcher(prevDispatcher) { + ReactCurrentDispatcher.current = prevDispatcher; + } - current = current.return; - } - } + function pushCacheDispatcher() { + { + var prevCacheDispatcher = ReactCurrentCache.current; + ReactCurrentCache.current = DefaultCacheDispatcher; + return prevCacheDispatcher; } } - if (enableTransitionTracing) { - var transition = ReactCurrentBatchConfig.transition; - - if (transition !== null && transition.name != null) { - if (transition.startTime === -1) { - transition.startTime = now$1(); - } - - addTransitionToLanesMap(root, transition, lane); + function popCacheDispatcher(prevCacheDispatcher) { + { + ReactCurrentCache.current = prevCacheDispatcher; } } - if (root === workInProgressRoot) { - // Received an update to a tree that's in the middle of rendering. Mark - // that there was an interleaved update work on this root. - if ((executionContext & RenderContext) === NoContext) { - workInProgressRootInterleavedUpdatedLanes = mergeLanes( - workInProgressRootInterleavedUpdatedLanes, - lane - ); + function markCommitTimeOfFallback() { + globalMostRecentFallbackTime = now$1(); + } + function markSkippedUpdateLanes(lane) { + workInProgressRootSkippedLanes = mergeLanes( + lane, + workInProgressRootSkippedLanes + ); + } + function renderDidSuspend() { + if (workInProgressRootExitStatus === RootInProgress) { + workInProgressRootExitStatus = RootSuspended; } + } + function renderDidSuspendDelayIfPossible() { + workInProgressRootExitStatus = RootSuspendedWithDelay; // Check if there are updates that we skipped tree that might have unblocked + // this render. - if (workInProgressRootExitStatus === RootSuspendedWithDelay) { - // The root already suspended with a delay, which means this render - // definitely won't finish. Since we have a new update, let's mark it as - // suspended now, right before marking the incoming update. This has the - // effect of interrupting the current render and switching to the update. - // TODO: Make sure this doesn't override pings that happen while we've - // already started rendering. + if ( + (includesNonIdleWork(workInProgressRootSkippedLanes) || + includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes)) && + workInProgressRoot !== null + ) { + // Mark the current render as suspended so that we switch to working on + // the updates that were skipped. Usually we only suspend at the end of + // the render phase. + // TODO: We should probably always mark the root as suspended immediately + // (inside this function), since by suspending at the end of the render + // phase introduces a potential mistake where we suspend lanes that were + // pinged or updated while we were rendering. + // TODO: Consider unwinding immediately, using the + // SuspendedOnHydration mechanism. markRootSuspended( - root, + workInProgressRoot, workInProgressRootRenderLanes, workInProgressDeferredLane ); } } + function renderDidError(error) { + if (workInProgressRootExitStatus !== RootSuspendedWithDelay) { + workInProgressRootExitStatus = RootErrored; + } - ensureRootIsScheduled(root); + if (workInProgressRootConcurrentErrors === null) { + workInProgressRootConcurrentErrors = [error]; + } else { + workInProgressRootConcurrentErrors.push(error); + } + } // Called during render to determine if anything has suspended. + // Returns false if we're not sure. + + function renderHasNotSuspendedYet() { + // If something errored or completed, we can't really be sure, + // so those are false. + return workInProgressRootExitStatus === RootInProgress; + } // TODO: Over time, this function and renderRootConcurrent have become more + // and more similar. Not sure it makes sense to maintain forked paths. Consider + // unifying them again. + + function renderRootSync(root, lanes) { + var prevExecutionContext = executionContext; + executionContext |= RenderContext; + var prevDispatcher = pushDispatcher(); + var prevCacheDispatcher = pushCacheDispatcher(); // If the root or lanes have changed, throw out the existing stack + // and prepare a fresh one. Otherwise we'll continue where we left off. - if ( - lane === SyncLane && - executionContext === NoContext && - (fiber.mode & ConcurrentMode) === NoMode - ) { - if (ReactCurrentActQueue.isBatchingLegacy); - else { - // Flush the synchronous work now, unless we're already working or inside - // a batch. This is intentionally inside scheduleUpdateOnFiber instead of - // scheduleCallbackForFiber to preserve the ability to schedule a callback - // without immediately flushing it. We only do this for user-initiated - // updates, to preserve historical behavior of legacy mode. - resetRenderTimer(); - flushSyncWorkOnLegacyRootsOnly(); + if ( + workInProgressRoot !== root || + workInProgressRootRenderLanes !== lanes + ) { + { + if (isDevToolsPresent) { + var memoizedUpdaters = root.memoizedUpdaters; + + if (memoizedUpdaters.size > 0) { + restorePendingUpdaters(root, workInProgressRootRenderLanes); + memoizedUpdaters.clear(); + } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set. + // If we bailout on this work, we'll move them back (like above). + // It's important to move them now in case the work spawns more work at the same priority with different updaters. + // That way we can keep the current update and future updates separate. + + movePendingFibersToMemoized(root, lanes); + } + } + + workInProgressTransitions = getTransitionsForLanes(root, lanes); + prepareFreshStack(root, lanes); } - } - } -} -function isUnsafeClassRenderPhaseUpdate(fiber) { - // Check if this is a render phase update. Only called by class components, - // which special (deprecated) behavior for UNSAFE_componentWillReceive props. - return (executionContext & RenderContext) !== NoContext; -} // This is the entry point for every concurrent task, i.e. anything that -// goes through Scheduler. - -function performConcurrentWorkOnRoot(root, didTimeout) { - { - resetNestedUpdateFlag(); - } - - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - throw new Error("Should not already be working."); - } // Flush any pending passive effects before deciding which lanes to work on, - // in case they schedule additional work. - - var originalCallbackNode = root.callbackNode; - var didFlushPassiveEffects = flushPassiveEffects(); - - if (didFlushPassiveEffects) { - // Something in the passive effect phase may have canceled the current task. - // Check if the task node for this root was changed. - if (root.callbackNode !== originalCallbackNode) { - // The current task was canceled. Exit. We don't need to call - // `ensureRootIsScheduled` because the check above implies either that - // there's a new task, or that there's no remaining work on this root. - return null; - } - } // Determine the next lanes to work on, using the fields stored - // on the root. - // TODO: This was already computed in the caller. Pass it as an argument. - - var lanes = getNextLanes( - root, - root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes - ); - - if (lanes === NoLanes) { - // Defensive coding. This is never expected to happen. - return null; - } // We disable time-slicing in some cases: if the work has been CPU-bound - // for too long ("expired" work, to prevent starvation), or we're in - // sync-updates-by-default mode. - // TODO: We only check `didTimeout` defensively, to account for a Scheduler - // bug we're still investigating. Once the bug in Scheduler is fixed, - // we can remove this, since we track expiration ourselves. - - var shouldTimeSlice = - !includesBlockingLane(root, lanes) && - !includesExpiredLane(root, lanes) && - (disableSchedulerTimeoutInWorkLoop || !didTimeout); - var exitStatus = shouldTimeSlice - ? renderRootConcurrent(root, lanes) - : renderRootSync(root, lanes); - - if (exitStatus !== RootInProgress) { - var renderWasConcurrent = shouldTimeSlice; - - do { - if (exitStatus === RootDidNotComplete) { - // The render unwound without completing the tree. This happens in special - // cases where need to exit the current render without producing a - // consistent tree or committing. - markRootSuspended(root, lanes, NoLane); - } else { - // The render completed. - // Check if this render may have yielded to a concurrent event, and if so, - // confirm that any newly rendered stores are consistent. - // TODO: It's possible that even a concurrent render may never have yielded - // to the main thread, if it was fast enough, or if it expired. We could - // skip the consistency check in that case, too. - var finishedWork = root.current.alternate; - if ( - renderWasConcurrent && - !isRenderConsistentWithExternalStores(finishedWork) - ) { - // A store was mutated in an interleaved event. Render again, - // synchronously, to block further mutations. - exitStatus = renderRootSync(root, lanes); // We assume the tree is now consistent because we didn't yield to any - // concurrent events. + { + if (enableDebugTracing) { + logRenderStarted(lanes); + } + } - renderWasConcurrent = false; // Need to check the exit status again. + if (enableSchedulingProfiler) { + markRenderStarted(lanes); + } - continue; - } // Check if something threw + var didSuspendInShell = false; - if (exitStatus === RootErrored) { - var originallyAttemptedLanes = lanes; - var errorRetryLanes = getLanesToRetrySynchronouslyOnError( - root, - originallyAttemptedLanes - ); + outer: do { + try { + if ( + workInProgressSuspendedReason !== NotSuspended && + workInProgress !== null + ) { + // The work loop is suspended. During a synchronous render, we don't + // yield to the main thread. Immediately unwind the stack. This will + // trigger either a fallback or an error boundary. + // TODO: For discrete and "default" updates (anything that's not + // flushSync), we want to wait for the microtasks the flush before + // unwinding. Will probably implement this using renderRootConcurrent, + // or merge renderRootSync and renderRootConcurrent into the same + // function and fork the behavior some other way. + var unitOfWork = workInProgress; + var thrownValue = workInProgressThrownValue; + + switch (workInProgressSuspendedReason) { + case SuspendedOnHydration: { + // Selective hydration. An update flowed into a dehydrated tree. + // Interrupt the current render so the work loop can switch to the + // hydration lane. + resetWorkInProgressStack(); + workInProgressRootExitStatus = RootDidNotComplete; + break outer; + } - if (errorRetryLanes !== NoLanes) { - lanes = errorRetryLanes; - exitStatus = recoverFromConcurrentError( - root, - originallyAttemptedLanes, - errorRetryLanes - ); - renderWasConcurrent = false; + case SuspendedOnImmediate: + case SuspendedOnData: { + if (!didSuspendInShell && getSuspenseHandler() === null) { + didSuspendInShell = true; + } // Intentional fallthrough + } + + default: { + // Unwind then continue with the normal work loop. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + throwAndUnwindWorkLoop(unitOfWork, thrownValue); + break; + } + } } + + workLoopSync(); + break; + } catch (thrownValue) { + handleThrow(root, thrownValue); } + } while (true); // Check if something suspended in the shell. We use this to detect an + // infinite ping loop caused by an uncached promise. + // + // Only increment this counter once per synchronous render attempt across the + // whole tree. Even if there are many sibling components that suspend, this + // counter only gets incremented once. + + if (didSuspendInShell) { + root.shellSuspendCounter++; + } + + resetContextDependencies(); + executionContext = prevExecutionContext; + popDispatcher(prevDispatcher); + popCacheDispatcher(prevCacheDispatcher); - if (exitStatus === RootFatalErrored) { - var fatalError = workInProgressRootFatalError; - prepareFreshStack(root, NoLanes); - markRootSuspended(root, lanes, NoLane); - ensureRootIsScheduled(root); - throw fatalError; - } // We now have a consistent tree. The next step is either to commit it, - // or, if something suspended, wait to commit it after a timeout. + if (workInProgress !== null) { + // This is a sync render, so we should have finished the whole tree. + throw new Error( + "Cannot commit an incomplete root. This error is likely caused by a " + + "bug in React. Please file an issue." + ); + } - root.finishedWork = finishedWork; - root.finishedLanes = lanes; - finishConcurrentRender(root, exitStatus, finishedWork, lanes); + { + if (enableDebugTracing) { + logRenderStopped(); + } } - break; - } while (true); - } + if (enableSchedulingProfiler) { + markRenderStopped(); + } // Set this to null to indicate there's no in-progress render. - ensureRootIsScheduled(root); - return getContinuationForRoot(root, originalCallbackNode); -} + workInProgressRoot = null; + workInProgressRootRenderLanes = NoLanes; // It's safe to process the queue now that the render phase is complete. -function recoverFromConcurrentError( - root, - originallyAttemptedLanes, - errorRetryLanes -) { - // If an error occurred during hydration, discard server response and fall - // back to client side render. - // Before rendering again, save the errors from the previous attempt. - var errorsFromFirstAttempt = workInProgressRootConcurrentErrors; - var wasRootDehydrated = isRootDehydrated(root); - - if (wasRootDehydrated) { - // The shell failed to hydrate. Set a flag to force a client rendering - // during the next attempt. To do this, we call prepareFreshStack now - // to create the root work-in-progress fiber. This is a bit weird in terms - // of factoring, because it relies on renderRootSync not calling - // prepareFreshStack again in the call below, which happens because the - // root and lanes haven't changed. - // - // TODO: I think what we should do is set ForceClientRender inside - // throwException, like we do for nested Suspense boundaries. The reason - // it's here instead is so we can switch to the synchronous work loop, too. - // Something to consider for a future refactor. - var rootWorkInProgress = prepareFreshStack(root, errorRetryLanes); - rootWorkInProgress.flags |= ForceClientRender; + finishQueueingConcurrentUpdates(); + return workInProgressRootExitStatus; + } // The work loop is an extremely hot path. Tell Closure not to inline it. - { - errorHydratingContainer(); + /** @noinline */ + + function workLoopSync() { + // Perform work without checking if we need to yield between fiber. + while (workInProgress !== null) { + performUnitOfWork(workInProgress); + } } - } - var exitStatus = renderRootSync(root, errorRetryLanes); + function renderRootConcurrent(root, lanes) { + var prevExecutionContext = executionContext; + executionContext |= RenderContext; + var prevDispatcher = pushDispatcher(); + var prevCacheDispatcher = pushCacheDispatcher(); // If the root or lanes have changed, throw out the existing stack + // and prepare a fresh one. Otherwise we'll continue where we left off. - if (exitStatus !== RootErrored) { - // Successfully finished rendering on retry - if (workInProgressRootDidAttachPingListener && !wasRootDehydrated) { - // During the synchronous render, we attached additional ping listeners. - // This is highly suggestive of an uncached promise (though it's not the - // only reason this would happen). If it was an uncached promise, then - // it may have masked a downstream error from ocurring without actually - // fixing it. Example: - // - // use(Promise.resolve('uncached')) - // throw new Error('Oops!') - // - // When this happens, there's a conflict between blocking potential - // concurrent data races and unwrapping uncached promise values. We - // have to choose one or the other. Because the data race recovery is - // a last ditch effort, we'll disable it. - root.errorRecoveryDisabledLanes = mergeLanes( - root.errorRecoveryDisabledLanes, - originallyAttemptedLanes - ); // Mark the current render as suspended and force it to restart. Once - // these lanes finish successfully, we'll re-enable the error recovery - // mechanism for subsequent updates. - - workInProgressRootInterleavedUpdatedLanes |= originallyAttemptedLanes; - return RootSuspendedWithDelay; - } // The errors from the failed first attempt have been recovered. Add - // them to the collection of recoverable errors. We'll log them in the - // commit phase. - - var errorsFromSecondAttempt = workInProgressRootRecoverableErrors; - workInProgressRootRecoverableErrors = errorsFromFirstAttempt; // The errors from the second attempt should be queued after the errors - // from the first attempt, to preserve the causal sequence. - - if (errorsFromSecondAttempt !== null) { - queueRecoverableErrors(errorsFromSecondAttempt); - } - } - - return exitStatus; -} + if ( + workInProgressRoot !== root || + workInProgressRootRenderLanes !== lanes + ) { + { + if (isDevToolsPresent) { + var memoizedUpdaters = root.memoizedUpdaters; + + if (memoizedUpdaters.size > 0) { + restorePendingUpdaters(root, workInProgressRootRenderLanes); + memoizedUpdaters.clear(); + } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set. + // If we bailout on this work, we'll move them back (like above). + // It's important to move them now in case the work spawns more work at the same priority with different updaters. + // That way we can keep the current update and future updates separate. + + movePendingFibersToMemoized(root, lanes); + } + } -function queueRecoverableErrors(errors) { - if (workInProgressRootRecoverableErrors === null) { - workInProgressRootRecoverableErrors = errors; - } else { - // $FlowFixMe[method-unbinding] - workInProgressRootRecoverableErrors.push.apply( - workInProgressRootRecoverableErrors, - errors - ); - } -} + workInProgressTransitions = getTransitionsForLanes(root, lanes); + resetRenderTimer(); + prepareFreshStack(root, lanes); + } -function finishConcurrentRender(root, exitStatus, finishedWork, lanes) { - // TODO: The fact that most of these branches are identical suggests that some - // of the exit statuses are not best modeled as exit statuses and should be - // tracked orthogonally. - switch (exitStatus) { - case RootInProgress: - case RootFatalErrored: { - throw new Error("Root did not complete. This is a bug in React."); - } - - case RootSuspendedWithDelay: { - if (includesOnlyTransitions(lanes)) { - // This is a transition, so we should exit without committing a - // placeholder and without scheduling a timeout. Delay indefinitely - // until we receive more data. - markRootSuspended(root, lanes, workInProgressDeferredLane); - return; - } // Commit the placeholder. + { + if (enableDebugTracing) { + logRenderStarted(lanes); + } + } - break; - } + if (enableSchedulingProfiler) { + markRenderStarted(lanes); + } - case RootErrored: - case RootSuspended: - case RootCompleted: { - break; - } + outer: do { + try { + if ( + workInProgressSuspendedReason !== NotSuspended && + workInProgress !== null + ) { + // The work loop is suspended. We need to either unwind the stack or + // replay the suspended component. + var unitOfWork = workInProgress; + var thrownValue = workInProgressThrownValue; + + resumeOrUnwind: switch (workInProgressSuspendedReason) { + case SuspendedOnError: { + // Unwind then continue with the normal work loop. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + throwAndUnwindWorkLoop(unitOfWork, thrownValue); + break; + } - default: { - throw new Error("Unknown root exit status."); - } - } + case SuspendedOnData: { + var thenable = thrownValue; - if (shouldForceFlushFallbacksInDEV()) { - // We're inside an `act` scope. Commit immediately. - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - workInProgressDeferredLane - ); - } else { - if ( - includesOnlyRetries(lanes) && - (alwaysThrottleRetries || exitStatus === RootSuspended) - ) { - // This render only included retries, no updates. Throttle committing - // retries so that we don't show too many loading states too quickly. - var msUntilTimeout = - globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now$1(); // Don't bother with a very short suspense time. - - if (msUntilTimeout > 10) { - markRootSuspended(root, lanes, workInProgressDeferredLane); - var nextLanes = getNextLanes(root, NoLanes); - - if (nextLanes !== NoLanes) { - // There's additional work we can do on this root. We might as well - // attempt to work on that while we're suspended. - return; - } // The render is suspended, it hasn't timed out, and there's no - // lower priority work to do. Instead of committing the fallback - // immediately, wait for more data to arrive. - // TODO: Combine retry throttling with Suspensey commits. Right now they - // run one after the other. - - root.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( - null, - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes, - workInProgressDeferredLane - ), - msUntilTimeout - ); - return; - } - } + if (isThenableResolved(thenable)) { + // The data resolved. Try rendering the component again. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + replaySuspendedUnitOfWork(unitOfWork); + break; + } // The work loop is suspended on data. We should wait for it to + // resolve before continuing to render. + // TODO: Handle the case where the promise resolves synchronously. + // Usually this is handled when we instrument the promise to add a + // `status` field, but if the promise already has a status, we won't + // have added a listener until right here. + + var onResolution = function () { + // Check if the root is still suspended on this promise. + if ( + workInProgressSuspendedReason === SuspendedOnData && + workInProgressRoot === root + ) { + // Mark the root as ready to continue rendering. + workInProgressSuspendedReason = SuspendedAndReadyToContinue; + } // Ensure the root is scheduled. We should do this even if we're + // currently working on a different root, so that we resume + // rendering later. + + ensureRootIsScheduled(root); + }; + + thenable.then(onResolution, onResolution); + break outer; + } - commitRootWhenReady( - root, - finishedWork, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - lanes, - workInProgressDeferredLane - ); - } -} + case SuspendedOnImmediate: { + // If this fiber just suspended, it's possible the data is already + // cached. Yield to the main thread to give it a chance to ping. If + // it does, we can retry immediately without unwinding the stack. + workInProgressSuspendedReason = SuspendedAndReadyToContinue; + break outer; + } -function commitRootWhenReady( - root, - finishedWork, - recoverableErrors, - transitions, - lanes, - spawnedLane -) { - // TODO: Combine retry throttling with Suspensey commits. Right now they run - // one after the other. - if (includesOnlyNonUrgentLanes(lanes)) { - // the suspensey resources. The renderer is responsible for accumulating - // all the load events. This all happens in a single synchronous - // transaction, so it track state in its own module scope. - - accumulateSuspenseyCommit(finishedWork); // At the end, ask the renderer if it's ready to commit, or if we should - // suspend. If it's not ready, it will return a callback to subscribe to - // a ready event. - - var schedulePendingCommit = waitForCommitToBeReady(); - - if (schedulePendingCommit !== null) { - // NOTE: waitForCommitToBeReady returns a subscribe function so that we - // only allocate a function if the commit isn't ready yet. The other - // pattern would be to always pass a callback to waitForCommitToBeReady. - // Not yet ready to commit. Delay the commit until the renderer notifies - // us that it's ready. This will be canceled if we start work on the - // root again. - root.cancelPendingCommit = schedulePendingCommit( - commitRoot.bind(null, root, recoverableErrors, transitions) - ); - markRootSuspended(root, lanes, spawnedLane); - return; - } - } // Otherwise, commit immediately. + case SuspendedOnInstance: { + workInProgressSuspendedReason = + SuspendedOnInstanceAndReadyToContinue; + break outer; + } - commitRoot(root, recoverableErrors, transitions, spawnedLane); -} + case SuspendedAndReadyToContinue: { + var _thenable = thrownValue; + + if (isThenableResolved(_thenable)) { + // The data resolved. Try rendering the component again. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + replaySuspendedUnitOfWork(unitOfWork); + } else { + // Otherwise, unwind then continue with the normal work loop. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + throwAndUnwindWorkLoop(unitOfWork, thrownValue); + } -function isRenderConsistentWithExternalStores(finishedWork) { - // Search the rendered tree for external store reads, and check whether the - // stores were mutated in a concurrent event. Intentionally using an iterative - // loop instead of recursion so we can exit early. - var node = finishedWork; + break; + } - while (true) { - if (node.flags & StoreConsistency) { - var updateQueue = node.updateQueue; + case SuspendedOnInstanceAndReadyToContinue: { + switch (workInProgress.tag) { + case HostComponent: + case HostHoistable: + case HostSingleton: { + // Before unwinding the stack, check one more time if the + // instance is ready. It may have loaded when React yielded to + // the main thread. + // Assigning this to a constant so Flow knows the binding won't + // be mutated by `preloadInstance`. + var hostFiber = workInProgress; + var type = hostFiber.type; + var props = hostFiber.pendingProps; + var isReady = preloadInstance(type, props); + + if (isReady) { + // The data resolved. Resume the work loop as if nothing + // suspended. Unlike when a user component suspends, we don't + // have to replay anything because the host fiber + // already completed. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + var sibling = hostFiber.sibling; + + if (sibling !== null) { + workInProgress = sibling; + } else { + var returnFiber = hostFiber.return; + + if (returnFiber !== null) { + workInProgress = returnFiber; + completeUnitOfWork(returnFiber); + } else { + workInProgress = null; + } + } + + break resumeOrUnwind; + } - if (updateQueue !== null) { - var checks = updateQueue.stores; + break; + } - if (checks !== null) { - for (var i = 0; i < checks.length; i++) { - var check = checks[i]; - var getSnapshot = check.getSnapshot; - var renderedValue = check.value; + default: { + // This will fail gracefully but it's not correct, so log a + // warning in dev. + if (true) { + error( + "Unexpected type of fiber triggered a suspensey commit. " + + "This is a bug in React." + ); + } - try { - if (!objectIs(getSnapshot(), renderedValue)) { - // Found an inconsistent store. - return false; + break; + } + } // Otherwise, unwind then continue with the normal work loop. + + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + throwAndUnwindWorkLoop(unitOfWork, thrownValue); + break; + } + + case SuspendedOnDeprecatedThrowPromise: { + // Suspended by an old implementation that uses the `throw promise` + // pattern. The newer replaying behavior can cause subtle issues + // like infinite ping loops. So we maintain the old behavior and + // always unwind. + workInProgressSuspendedReason = NotSuspended; + workInProgressThrownValue = null; + throwAndUnwindWorkLoop(unitOfWork, thrownValue); + break; + } + + case SuspendedOnHydration: { + // Selective hydration. An update flowed into a dehydrated tree. + // Interrupt the current render so the work loop can switch to the + // hydration lane. + resetWorkInProgressStack(); + workInProgressRootExitStatus = RootDidNotComplete; + break outer; + } + + default: { + throw new Error( + "Unexpected SuspendedReason. This is a bug in React." + ); } - } catch (error) { - // If `getSnapshot` throws, return `false`. This will schedule - // a re-render, and the error will be rethrown during render. - return false; } } + + if (true && ReactCurrentActQueue.current !== null) { + // `act` special case: If we're inside an `act` scope, don't consult + // `shouldYield`. Always keep working until the render is complete. + // This is not just an optimization: in a unit test environment, we + // can't trust the result of `shouldYield`, because the host I/O is + // likely mocked. + workLoopSync(); + } else { + workLoopConcurrent(); + } + + break; + } catch (thrownValue) { + handleThrow(root, thrownValue); } - } - } + } while (true); + + resetContextDependencies(); + popDispatcher(prevDispatcher); + popCacheDispatcher(prevCacheDispatcher); + executionContext = prevExecutionContext; + + { + if (enableDebugTracing) { + logRenderStopped(); + } + } // Check if the tree has completed. + + if (workInProgress !== null) { + // Still work remaining. + if (enableSchedulingProfiler) { + markRenderYielded(); + } + + return RootInProgress; + } else { + // Completed the tree. + if (enableSchedulingProfiler) { + markRenderStopped(); + } // Set this to null to indicate there's no in-progress render. + + workInProgressRoot = null; + workInProgressRootRenderLanes = NoLanes; // It's safe to process the queue now that the render phase is complete. - var child = node.child; + finishQueueingConcurrentUpdates(); // Return the final exit status. - if (node.subtreeFlags & StoreConsistency && child !== null) { - child.return = node; - node = child; - continue; + return workInProgressRootExitStatus; + } } + /** @noinline */ - if (node === finishedWork) { - return true; + function workLoopConcurrent() { + // Perform work until Scheduler asks us to yield + while (workInProgress !== null && !shouldYield()) { + // $FlowFixMe[incompatible-call] found when upgrading Flow + performUnitOfWork(workInProgress); + } } - while (node.sibling === null) { - if (node.return === null || node.return === finishedWork) { - return true; + function performUnitOfWork(unitOfWork) { + // The current, flushed, state of this fiber is the alternate. Ideally + // nothing should rely on this, but relying on it here means that we don't + // need an additional field on the work in progress. + var current = unitOfWork.alternate; + setCurrentFiber(unitOfWork); + var next; + + if ((unitOfWork.mode & ProfileMode) !== NoMode) { + startProfilerTimer(unitOfWork); + next = beginWork(current, unitOfWork, entangledRenderLanes); + stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); + } else { + next = beginWork(current, unitOfWork, entangledRenderLanes); + } + + resetCurrentFiber(); + unitOfWork.memoizedProps = unitOfWork.pendingProps; + + if (next === null) { + // If this doesn't spawn new work, complete the current work. + completeUnitOfWork(unitOfWork); + } else { + workInProgress = next; } - node = node.return; + ReactCurrentOwner.current = null; } - node.sibling.return = node.return; - node = node.sibling; - } // Flow doesn't know this is unreachable, but eslint does - // eslint-disable-next-line no-unreachable + function replaySuspendedUnitOfWork(unitOfWork) { + // This is a fork of performUnitOfWork specifcally for replaying a fiber that + // just suspended. + // + var current = unitOfWork.alternate; + setCurrentFiber(unitOfWork); + var next; + setCurrentFiber(unitOfWork); + var isProfilingMode = (unitOfWork.mode & ProfileMode) !== NoMode; - return true; -} + if (isProfilingMode) { + startProfilerTimer(unitOfWork); + } -function markRootSuspended(root, suspendedLanes, spawnedLane) { - // When suspending, we should always exclude lanes that were pinged or (more - // rarely, since we try to avoid it) updated during the render phase. - // TODO: Lol maybe there's a better way to factor this besides this - // obnoxiously named function :) - suspendedLanes = removeLanes(suspendedLanes, workInProgressRootPingedLanes); - suspendedLanes = removeLanes( - suspendedLanes, - workInProgressRootInterleavedUpdatedLanes - ); - markRootSuspended$1(root, suspendedLanes, spawnedLane); -} // This is the entry point for synchronous tasks that don't go -// through Scheduler - -function performSyncWorkOnRoot(root, lanes) { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - throw new Error("Should not already be working."); - } - - var didFlushPassiveEffects = flushPassiveEffects(); - - if (didFlushPassiveEffects) { - // If passive effects were flushed, exit to the outer work loop in the root - // scheduler, so we can recompute the priority. - // TODO: We don't actually need this `ensureRootIsScheduled` call because - // this path is only reachable if the root is already part of the schedule. - // I'm including it only for consistency with the other exit points from - // this function. Can address in a subsequent refactor. - ensureRootIsScheduled(root); - return null; - } - - { - syncNestedUpdateFlag(); - } - - var exitStatus = renderRootSync(root, lanes); - - if (root.tag !== LegacyRoot && exitStatus === RootErrored) { - // If something threw an error, try rendering one more time. We'll render - // synchronously to block concurrent data mutations, and we'll includes - // all pending updates are included. If it still fails after the second - // attempt, we'll give up and commit the resulting tree. - var originallyAttemptedLanes = lanes; - var errorRetryLanes = getLanesToRetrySynchronouslyOnError( - root, - originallyAttemptedLanes - ); + switch (unitOfWork.tag) { + case IndeterminateComponent: { + // Because it suspended with `use`, we can assume it's a + // function component. + unitOfWork.tag = FunctionComponent; // Fallthrough to the next branch. + } + + case SimpleMemoComponent: + case FunctionComponent: { + // Resolve `defaultProps`. This logic is copied from `beginWork`. + // TODO: Consider moving this switch statement into that module. Also, + // could maybe use this as an opportunity to say `use` doesn't work with + // `defaultProps` :) + var Component = unitOfWork.type; + var unresolvedProps = unitOfWork.pendingProps; + var resolvedProps = + unitOfWork.elementType === Component + ? unresolvedProps + : resolveDefaultProps(Component, unresolvedProps); + var context; + + next = replayFunctionComponent( + current, + unitOfWork, + resolvedProps, + Component, + context, + workInProgressRootRenderLanes + ); + break; + } - if (errorRetryLanes !== NoLanes) { - lanes = errorRetryLanes; - exitStatus = recoverFromConcurrentError( - root, - originallyAttemptedLanes, - errorRetryLanes - ); - } - } - - if (exitStatus === RootFatalErrored) { - var fatalError = workInProgressRootFatalError; - prepareFreshStack(root, NoLanes); - markRootSuspended(root, lanes, NoLane); - ensureRootIsScheduled(root); - throw fatalError; - } - - if (exitStatus === RootDidNotComplete) { - // The render unwound without completing the tree. This happens in special - // cases where need to exit the current render without producing a - // consistent tree or committing. - markRootSuspended(root, lanes, NoLane); - ensureRootIsScheduled(root); - return null; - } // We now have a consistent tree. Because this is a sync render, we - // will commit it even if something suspended. - - var finishedWork = root.current.alternate; - root.finishedWork = finishedWork; - root.finishedLanes = lanes; - commitRoot( - root, - workInProgressRootRecoverableErrors, - workInProgressTransitions, - workInProgressDeferredLane - ); // Before exiting, make sure there's a callback scheduled for the next - // pending level. - - ensureRootIsScheduled(root); - return null; -} -function getExecutionContext() { - return executionContext; -} -// Warning, this opts-out of checking the function body. -// eslint-disable-next-line no-unused-vars -// eslint-disable-next-line no-redeclare -// eslint-disable-next-line no-redeclare - -function flushSync(fn) { - // In legacy mode, we flush pending passive effects at the beginning of the - // next event, not at the end of the previous one. - if ( - rootWithPendingPassiveEffects !== null && - rootWithPendingPassiveEffects.tag === LegacyRoot && - (executionContext & (RenderContext | CommitContext)) === NoContext - ) { - flushPassiveEffects(); - } - - var prevExecutionContext = executionContext; - executionContext |= BatchedContext; - var prevTransition = ReactCurrentBatchConfig.transition; - var previousPriority = getCurrentUpdatePriority(); - - try { - ReactCurrentBatchConfig.transition = null; - setCurrentUpdatePriority(DiscreteEventPriority); - - if (fn) { - return fn(); - } else { - return undefined; - } - } finally { - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; - executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. - // Note that this will happen even if batchedUpdates is higher up - // the stack. + case ForwardRef: { + // Resolve `defaultProps`. This logic is copied from `beginWork`. + // TODO: Consider moving this switch statement into that module. Also, + // could maybe use this as an opportunity to say `use` doesn't work with + // `defaultProps` :) + var _Component = unitOfWork.type.render; + var _unresolvedProps = unitOfWork.pendingProps; - if ((executionContext & (RenderContext | CommitContext)) === NoContext) { - flushSyncWorkOnAllRoots(); - } - } -} -function isInvalidExecutionContextForEventFunction() { - // Used to throw if certain APIs are called from the wrong context. - return (executionContext & RenderContext) !== NoContext; -} // This is called by the HiddenContext module when we enter or leave a -// hidden subtree. The stack logic is managed there because that's the only -// place that ever modifies it. Which module it lives in doesn't matter for -// performance because this function will get inlined regardless - -function setEntangledRenderLanes(newEntangledRenderLanes) { - entangledRenderLanes = newEntangledRenderLanes; -} -function getEntangledRenderLanes() { - return entangledRenderLanes; -} + var _resolvedProps = + unitOfWork.elementType === _Component + ? _unresolvedProps + : resolveDefaultProps(_Component, _unresolvedProps); + + next = replayFunctionComponent( + current, + unitOfWork, + _resolvedProps, + _Component, + unitOfWork.ref, + workInProgressRootRenderLanes + ); + break; + } + + case HostComponent: { + // Some host components are stateful (that's how we implement form + // actions) but we don't bother to reuse the memoized state because it's + // not worth the extra code. The main reason to reuse the previous hooks + // is to reuse uncached promises, but we happen to know that the only + // promises that a host component might suspend on are definitely cached + // because they are controlled by us. So don't bother. + resetHooksOnUnwind(unitOfWork); // Fallthrough to the next branch. + } + + default: { + // Other types besides function components are reset completely before + // being replayed. Currently this only happens when a Usable type is + // reconciled — the reconciler will suspend. + // + // We reset the fiber back to its original state; however, this isn't + // a full "unwind" because we're going to reuse the promises that were + // reconciled previously. So it's intentional that we don't call + // resetSuspendedWorkLoopOnUnwind here. + unwindInterruptedWork(current, unitOfWork); + unitOfWork = workInProgress = resetWorkInProgress( + unitOfWork, + entangledRenderLanes + ); + next = beginWork(current, unitOfWork, entangledRenderLanes); + break; + } + } + + if (isProfilingMode) { + stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); + } // The begin phase finished successfully without suspending. Return to the + // normal work loop. -function resetWorkInProgressStack() { - if (workInProgress === null) return; - var interruptedWork; - - if (workInProgressSuspendedReason === NotSuspended) { - // Normal case. Work-in-progress hasn't started yet. Unwind all - // its parents. - interruptedWork = workInProgress.return; - } else { - // Work-in-progress is in suspended state. Reset the work loop and unwind - // both the suspended fiber and all its parents. - resetSuspendedWorkLoopOnUnwind(workInProgress); - interruptedWork = workInProgress; - } - - while (interruptedWork !== null) { - var current = interruptedWork.alternate; - unwindInterruptedWork(current, interruptedWork); - interruptedWork = interruptedWork.return; - } - - workInProgress = null; -} + resetCurrentFiber(); + unitOfWork.memoizedProps = unitOfWork.pendingProps; -function prepareFreshStack(root, lanes) { - root.finishedWork = null; - root.finishedLanes = NoLanes; - var timeoutHandle = root.timeoutHandle; - - if (timeoutHandle !== noTimeout) { - // The root previous suspended and scheduled a timeout to commit a fallback - // state. Now that we have additional work, cancel the timeout. - root.timeoutHandle = noTimeout; // $FlowFixMe[incompatible-call] Complains noTimeout is not a TimeoutID, despite the check above - - cancelTimeout(timeoutHandle); - } - - var cancelPendingCommit = root.cancelPendingCommit; - - if (cancelPendingCommit !== null) { - root.cancelPendingCommit = null; - cancelPendingCommit(); - } - - resetWorkInProgressStack(); - workInProgressRoot = root; - var rootWorkInProgress = createWorkInProgress(root.current, null); - workInProgress = rootWorkInProgress; - workInProgressRootRenderLanes = lanes; - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - workInProgressRootDidAttachPingListener = false; - workInProgressRootExitStatus = RootInProgress; - workInProgressRootFatalError = null; - workInProgressRootSkippedLanes = NoLanes; - workInProgressRootInterleavedUpdatedLanes = NoLanes; - workInProgressRootPingedLanes = NoLanes; - workInProgressDeferredLane = NoLane; - workInProgressRootConcurrentErrors = null; - workInProgressRootRecoverableErrors = null; // Get the lanes that are entangled with whatever we're about to render. We - // track these separately so we can distinguish the priority of the render - // task from the priority of the lanes it is entangled with. For example, a - // transition may not be allowed to finish unless it includes the Sync lane, - // which is currently suspended. We should be able to render the Transition - // and Sync lane in the same batch, but at Transition priority, because the - // Sync lane already suspended. - - entangledRenderLanes = getEntangledLanes(root, lanes); - finishQueueingConcurrentUpdates(); - - { - ReactStrictModeWarnings.discardPendingWarnings(); - } - - return rootWorkInProgress; -} + if (next === null) { + // If this doesn't spawn new work, complete the current work. + completeUnitOfWork(unitOfWork); + } else { + workInProgress = next; + } -function resetSuspendedWorkLoopOnUnwind(fiber) { - // Reset module-level state that was set during the render phase. - resetContextDependencies(); - resetHooksOnUnwind(fiber); - resetChildReconcilerOnUnwind(); -} + ReactCurrentOwner.current = null; + } -function handleThrow(root, thrownValue) { - // A component threw an exception. Usually this is because it suspended, but - // it also includes regular program errors. - // - // We're either going to unwind the stack to show a Suspense or error - // boundary, or we're going to replay the component again. Like after a - // promise resolves. - // - // Until we decide whether we're going to unwind or replay, we should preserve - // the current state of the work loop without resetting anything. - // - // If we do decide to unwind the stack, module-level variables will be reset - // in resetSuspendedWorkLoopOnUnwind. - // These should be reset immediately because they're only supposed to be set - // when React is executing user code. - resetHooksAfterThrow(); - resetCurrentFiber(); - ReactCurrentOwner.current = null; - - if (thrownValue === SuspenseException) { - // This is a special type of exception used for Suspense. For historical - // reasons, the rest of the Suspense implementation expects the thrown value - // to be a thenable, because before `use` existed that was the (unstable) - // API for suspending. This implementation detail can change later, once we - // deprecate the old API in favor of `use`. - thrownValue = getSuspendedThenable(); - workInProgressSuspendedReason = - shouldRemainOnPreviousScreen() && // Check if there are other pending updates that might possibly unblock this - // component from suspending. This mirrors the check in - // renderDidSuspendDelayIfPossible. We should attempt to unify them somehow. - // TODO: Consider unwinding immediately, using the - // SuspendedOnHydration mechanism. - !includesNonIdleWork(workInProgressRootSkippedLanes) && - !includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes) // Suspend work loop until data resolves - ? SuspendedOnData // Don't suspend work loop, except to check if the data has - : // immediately resolved (i.e. in a microtask). Otherwise, trigger the - // nearest Suspense fallback. - SuspendedOnImmediate; - } else if (thrownValue === SuspenseyCommitException) { - thrownValue = getSuspendedThenable(); - workInProgressSuspendedReason = SuspendedOnInstance; - } else if (thrownValue === SelectiveHydrationException) { - // An update flowed into a dehydrated boundary. Before we can apply the - // update, we need to finish hydrating. Interrupt the work-in-progress - // render so we can restart at the hydration lane. - // - // The ideal implementation would be able to switch contexts without - // unwinding the current stack. - // - // We could name this something more general but as of now it's the only - // case where we think this should happen. - workInProgressSuspendedReason = SuspendedOnHydration; - } else { - // This is a regular error. - var isWakeable = - thrownValue !== null && - typeof thrownValue === "object" && - typeof thrownValue.then === "function"; - workInProgressSuspendedReason = isWakeable // A wakeable object was thrown by a legacy Suspense implementation. - ? // This has slightly different behavior than suspending with `use`. - SuspendedOnDeprecatedThrowPromise // This is a regular error. If something earlier in the component already - : // suspended, we must clear the thenable state to unblock the work loop. - SuspendedOnError; - } - - workInProgressThrownValue = thrownValue; - var erroredWork = workInProgress; - - if (erroredWork === null) { - // This is a fatal error - workInProgressRootExitStatus = RootFatalErrored; - workInProgressRootFatalError = thrownValue; - return; - } - - if (erroredWork.mode & ProfileMode) { - // Record the time spent rendering before an error was thrown. This - // avoids inaccurate Profiler durations in the case of a - // suspended render. - stopProfilerTimerIfRunningAndRecordDelta(erroredWork, true); - } - - if (enableSchedulingProfiler) { - markComponentRenderStopped(); - - switch (workInProgressSuspendedReason) { - case SuspendedOnError: { - markComponentErrored( - erroredWork, + function throwAndUnwindWorkLoop(unitOfWork, thrownValue) { + // This is a fork of performUnitOfWork specifcally for unwinding a fiber + // that threw an exception. + // + // Return to the normal work loop. This will unwind the stack, and potentially + // result in showing a fallback. + resetSuspendedWorkLoopOnUnwind(unitOfWork); + var returnFiber = unitOfWork.return; + + if (returnFiber === null || workInProgressRoot === null) { + // Expected to be working on a non-root fiber. This is a fatal error + // because there's no ancestor that can handle it; the root is + // supposed to capture all errors that weren't caught by an error + // boundary. + workInProgressRootExitStatus = RootFatalErrored; + workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next + // sibling, or the parent if there are no siblings. But since the root + // has no siblings nor a parent, we set it to null. Usually this is + // handled by `completeUnitOfWork` or `unwindWork`, but since we're + // intentionally not calling those, we need set it here. + // TODO: Consider calling `unwindWork` to pop the contexts. + + workInProgress = null; + return; + } + + try { + // Find and mark the nearest Suspense or error boundary that can handle + // this "exception". + throwException( + workInProgressRoot, + returnFiber, + unitOfWork, thrownValue, workInProgressRootRenderLanes ); - break; + } catch (error) { + // We had trouble processing the error. An example of this happening is + // when accessing the `componentDidCatch` property of an error boundary + // throws an error. A weird edge case. There's a regression test for this. + // To prevent an infinite loop, bubble the error up to the next parent. + workInProgress = returnFiber; + throw error; } - case SuspendedOnData: - case SuspendedOnImmediate: - case SuspendedOnDeprecatedThrowPromise: - case SuspendedAndReadyToContinue: { - var wakeable = thrownValue; - markComponentSuspended( - erroredWork, - wakeable, - workInProgressRootRenderLanes - ); - break; + if (unitOfWork.flags & Incomplete) { + // Unwind the stack until we reach the nearest boundary. + unwindUnitOfWork(unitOfWork); + } else { + // Although the fiber suspended, we're intentionally going to commit it in + // an inconsistent state. We can do this safely in cases where we know the + // inconsistent tree will be hidden. + // + // This currently only applies to Legacy Suspense implementation, but we may + // port a version of this to concurrent roots, too, when performing a + // synchronous render. Because that will allow us to mutate the tree as we + // go instead of buffering mutations until the end. Though it's unclear if + // this particular path is how that would be implemented. + completeUnitOfWork(unitOfWork); } } - } -} -function shouldRemainOnPreviousScreen() { - // This is asking whether it's better to suspend the transition and remain - // on the previous screen, versus showing a fallback as soon as possible. It - // takes into account both the priority of render and also whether showing a - // fallback would produce a desirable user experience. - var handler = getSuspenseHandler(); - - if (handler === null) { - // There's no Suspense boundary that can provide a fallback. We have no - // choice but to remain on the previous screen. - // NOTE: We do this even for sync updates, for lack of any better option. In - // the future, we may change how we handle this, like by putting the whole - // root into a "detached" mode. - return true; - } // TODO: Once `use` has fully replaced the `throw promise` pattern, we should - // be able to remove the equivalent check in finishConcurrentRender, and rely - // just on this one. - - if (includesOnlyTransitions(workInProgressRootRenderLanes)) { - if (getShellBoundary() === null) { - // We're rendering inside the "shell" of the app. Activating the nearest - // fallback would cause visible content to disappear. It's better to - // suspend the transition and remain on the previous screen. - return true; - } else { - // We're rendering content that wasn't part of the previous screen. - // Rather than block the transition, it's better to show a fallback as - // soon as possible. The appearance of any nested fallbacks will be - // throttled to avoid jank. - return false; - } - } - - if ( - includesOnlyRetries(workInProgressRootRenderLanes) || // In this context, an OffscreenLane counts as a Retry - // TODO: It's become increasingly clear that Retries and Offscreen are - // deeply connected. They probably can be unified further. - includesSomeLane(workInProgressRootRenderLanes, OffscreenLane) - ) { - // During a retry, we can suspend rendering if the nearest Suspense boundary - // is the boundary of the "shell", because we're guaranteed not to block - // any new content from appearing. - // - // The reason we must check if this is a retry is because it guarantees - // that suspending the work loop won't block an actual update, because - // retries don't "update" anything; they fill in fallbacks that were left - // behind by a previous transition. - return handler === getShellBoundary(); - } // For all other Lanes besides Transitions and Retries, we should not wait - // for the data to load. - - return false; -} + function completeUnitOfWork(unitOfWork) { + // Attempt to complete the current unit of work, then move to the next + // sibling. If there are no more siblings, return to the parent fiber. + var completedWork = unitOfWork; -function pushDispatcher(container) { - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = ContextOnlyDispatcher; - - if (prevDispatcher === null) { - // The React isomorphic package does not include a default dispatcher. - // Instead the first renderer will lazily attach one, in order to give - // nicer error messages. - return ContextOnlyDispatcher; - } else { - return prevDispatcher; - } -} + do { + { + if ((completedWork.flags & Incomplete) !== NoFlags$1) { + // NOTE: If we re-enable sibling prerendering in some cases, this branch + // is where we would switch to the unwinding path. + error( + "Internal React error: Expected this fiber to be complete, but " + + "it isn't. It should have been unwound. This is a bug in React." + ); + } + } // The current, flushed, state of this fiber is the alternate. Ideally + // nothing should rely on this, but relying on it here means that we don't + // need an additional field on the work in progress. -function popDispatcher(prevDispatcher) { - ReactCurrentDispatcher.current = prevDispatcher; -} + var current = completedWork.alternate; + var returnFiber = completedWork.return; + setCurrentFiber(completedWork); + var next = void 0; -function pushCacheDispatcher() { - { - var prevCacheDispatcher = ReactCurrentCache.current; - ReactCurrentCache.current = DefaultCacheDispatcher; - return prevCacheDispatcher; - } -} + if ((completedWork.mode & ProfileMode) === NoMode) { + next = completeWork(current, completedWork, entangledRenderLanes); + } else { + startProfilerTimer(completedWork); + next = completeWork(current, completedWork, entangledRenderLanes); // Update render duration assuming we didn't error. -function popCacheDispatcher(prevCacheDispatcher) { - { - ReactCurrentCache.current = prevCacheDispatcher; - } -} + stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); + } -function markCommitTimeOfFallback() { - globalMostRecentFallbackTime = now$1(); -} -function markSkippedUpdateLanes(lane) { - workInProgressRootSkippedLanes = mergeLanes( - lane, - workInProgressRootSkippedLanes - ); -} -function renderDidSuspend() { - if (workInProgressRootExitStatus === RootInProgress) { - workInProgressRootExitStatus = RootSuspended; - } -} -function renderDidSuspendDelayIfPossible() { - workInProgressRootExitStatus = RootSuspendedWithDelay; // Check if there are updates that we skipped tree that might have unblocked - // this render. - - if ( - (includesNonIdleWork(workInProgressRootSkippedLanes) || - includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes)) && - workInProgressRoot !== null - ) { - // Mark the current render as suspended so that we switch to working on - // the updates that were skipped. Usually we only suspend at the end of - // the render phase. - // TODO: We should probably always mark the root as suspended immediately - // (inside this function), since by suspending at the end of the render - // phase introduces a potential mistake where we suspend lanes that were - // pinged or updated while we were rendering. - // TODO: Consider unwinding immediately, using the - // SuspendedOnHydration mechanism. - markRootSuspended( - workInProgressRoot, - workInProgressRootRenderLanes, - workInProgressDeferredLane - ); - } -} -function renderDidError(error) { - if (workInProgressRootExitStatus !== RootSuspendedWithDelay) { - workInProgressRootExitStatus = RootErrored; - } - - if (workInProgressRootConcurrentErrors === null) { - workInProgressRootConcurrentErrors = [error]; - } else { - workInProgressRootConcurrentErrors.push(error); - } -} // Called during render to determine if anything has suspended. -// Returns false if we're not sure. - -function renderHasNotSuspendedYet() { - // If something errored or completed, we can't really be sure, - // so those are false. - return workInProgressRootExitStatus === RootInProgress; -} // TODO: Over time, this function and renderRootConcurrent have become more -// and more similar. Not sure it makes sense to maintain forked paths. Consider -// unifying them again. - -function renderRootSync(root, lanes) { - var prevExecutionContext = executionContext; - executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(); - var prevCacheDispatcher = pushCacheDispatcher(); // If the root or lanes have changed, throw out the existing stack - // and prepare a fresh one. Otherwise we'll continue where we left off. - - if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { - { - if (isDevToolsPresent) { - var memoizedUpdaters = root.memoizedUpdaters; + resetCurrentFiber(); + + if (next !== null) { + // Completing this fiber spawned new work. Work on that next. + workInProgress = next; + return; + } - if (memoizedUpdaters.size > 0) { - restorePendingUpdaters(root, workInProgressRootRenderLanes); - memoizedUpdaters.clear(); - } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set. - // If we bailout on this work, we'll move them back (like above). - // It's important to move them now in case the work spawns more work at the same priority with different updaters. - // That way we can keep the current update and future updates separate. + var siblingFiber = completedWork.sibling; - movePendingFibersToMemoized(root, lanes); - } - } + if (siblingFiber !== null) { + // If there is more work to do in this returnFiber, do that next. + workInProgress = siblingFiber; + return; + } // Otherwise, return to the parent + // $FlowFixMe[incompatible-type] we bail out when we get a null + + completedWork = returnFiber; // Update the next thing we're working on in case something throws. - workInProgressTransitions = getTransitionsForLanes(root, lanes); - prepareFreshStack(root, lanes); - } + workInProgress = completedWork; + } while (completedWork !== null); // We've reached the root. - { - if (enableDebugTracing) { - logRenderStarted(lanes); + if (workInProgressRootExitStatus === RootInProgress) { + workInProgressRootExitStatus = RootCompleted; + } } - } - if (enableSchedulingProfiler) { - markRenderStarted(lanes); - } + function unwindUnitOfWork(unitOfWork) { + var incompleteWork = unitOfWork; - var didSuspendInShell = false; + do { + // The current, flushed, state of this fiber is the alternate. Ideally + // nothing should rely on this, but relying on it here means that we don't + // need an additional field on the work in progress. + var current = incompleteWork.alternate; // This fiber did not complete because something threw. Pop values off + // the stack without entering the complete phase. If this is a boundary, + // capture values if possible. + + var next = unwindWork(current, incompleteWork); // Because this fiber did not complete, don't reset its lanes. + + if (next !== null) { + // Found a boundary that can handle this exception. Re-renter the + // begin phase. This branch will return us to the normal work loop. + // + // Since we're restarting, remove anything that is not a host effect + // from the effect tag. + next.flags &= HostEffectMask; + workInProgress = next; + return; + } // Keep unwinding until we reach either a boundary or the root. - outer: do { - try { - if ( - workInProgressSuspendedReason !== NotSuspended && - workInProgress !== null - ) { - // The work loop is suspended. During a synchronous render, we don't - // yield to the main thread. Immediately unwind the stack. This will - // trigger either a fallback or an error boundary. - // TODO: For discrete and "default" updates (anything that's not - // flushSync), we want to wait for the microtasks the flush before - // unwinding. Will probably implement this using renderRootConcurrent, - // or merge renderRootSync and renderRootConcurrent into the same - // function and fork the behavior some other way. - var unitOfWork = workInProgress; - var thrownValue = workInProgressThrownValue; + if ((incompleteWork.mode & ProfileMode) !== NoMode) { + // Record the render duration for the fiber that errored. + stopProfilerTimerIfRunningAndRecordDelta(incompleteWork, false); // Include the time spent working on failed children before continuing. - switch (workInProgressSuspendedReason) { - case SuspendedOnHydration: { - // Selective hydration. An update flowed into a dehydrated tree. - // Interrupt the current render so the work loop can switch to the - // hydration lane. - resetWorkInProgressStack(); - workInProgressRootExitStatus = RootDidNotComplete; - break outer; - } + var actualDuration = incompleteWork.actualDuration; + var child = incompleteWork.child; - case SuspendedOnImmediate: - case SuspendedOnData: { - if (!didSuspendInShell && getSuspenseHandler() === null) { - didSuspendInShell = true; - } // Intentional fallthrough + while (child !== null) { + // $FlowFixMe[unsafe-addition] addition with possible null/undefined value + actualDuration += child.actualDuration; + child = child.sibling; } - default: { - // Unwind then continue with the normal work loop. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); - break; - } - } - } + incompleteWork.actualDuration = actualDuration; + } // TODO: Once we stop prerendering siblings, instead of resetting the parent + // of the node being unwound, we should be able to reset node itself as we + // unwind the stack. Saves an additional null check. - workLoopSync(); - break; - } catch (thrownValue) { - handleThrow(root, thrownValue); - } - } while (true); // Check if something suspended in the shell. We use this to detect an - // infinite ping loop caused by an uncached promise. - // - // Only increment this counter once per synchronous render attempt across the - // whole tree. Even if there are many sibling components that suspend, this - // counter only gets incremented once. + var returnFiber = incompleteWork.return; - if (didSuspendInShell) { - root.shellSuspendCounter++; - } + if (returnFiber !== null) { + // Mark the parent fiber as incomplete and clear its subtree flags. + // TODO: Once we stop prerendering siblings, we may be able to get rid of + // the Incomplete flag because unwinding to the nearest boundary will + // happen synchronously. + returnFiber.flags |= Incomplete; + returnFiber.subtreeFlags = NoFlags$1; + returnFiber.deletions = null; + } // NOTE: If we re-enable sibling prerendering in some cases, here we + // would switch to the normal completion path: check if a sibling + // exists, and if so, begin work on it. + // Otherwise, return to the parent + // $FlowFixMe[incompatible-type] we bail out when we get a null - resetContextDependencies(); - executionContext = prevExecutionContext; - popDispatcher(prevDispatcher); - popCacheDispatcher(prevCacheDispatcher); + incompleteWork = returnFiber; // Update the next thing we're working on in case something throws. - if (workInProgress !== null) { - // This is a sync render, so we should have finished the whole tree. - throw new Error( - "Cannot commit an incomplete root. This error is likely caused by a " + - "bug in React. Please file an issue." - ); - } + workInProgress = incompleteWork; + } while (incompleteWork !== null); // We've unwound all the way to the root. - { - if (enableDebugTracing) { - logRenderStopped(); + workInProgressRootExitStatus = RootDidNotComplete; + workInProgress = null; } - } - if (enableSchedulingProfiler) { - markRenderStopped(); - } // Set this to null to indicate there's no in-progress render. + function commitRoot(root, recoverableErrors, transitions, spawnedLane) { + // TODO: This no longer makes any sense. We already wrap the mutation and + // layout phases. Should be able to remove. + var previousUpdateLanePriority = getCurrentUpdatePriority(); + var prevTransition = ReactCurrentBatchConfig.transition; - workInProgressRoot = null; - workInProgressRootRenderLanes = NoLanes; // It's safe to process the queue now that the render phase is complete. + try { + ReactCurrentBatchConfig.transition = null; + setCurrentUpdatePriority(DiscreteEventPriority); + commitRootImpl( + root, + recoverableErrors, + transitions, + previousUpdateLanePriority, + spawnedLane + ); + } finally { + ReactCurrentBatchConfig.transition = prevTransition; + setCurrentUpdatePriority(previousUpdateLanePriority); + } - finishQueueingConcurrentUpdates(); - return workInProgressRootExitStatus; -} // The work loop is an extremely hot path. Tell Closure not to inline it. + return null; + } -/** @noinline */ + function commitRootImpl( + root, + recoverableErrors, + transitions, + renderPriorityLevel, + spawnedLane + ) { + do { + // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which + // means `flushPassiveEffects` will sometimes result in additional + // passive effects. So we need to keep flushing in a loop until there are + // no more pending effects. + // TODO: Might be better if `flushPassiveEffects` did not automatically + // flush synchronous work at the end, to avoid factoring hazards like this. + flushPassiveEffects(); + } while (rootWithPendingPassiveEffects !== null); -function workLoopSync() { - // Perform work without checking if we need to yield between fiber. - while (workInProgress !== null) { - performUnitOfWork(workInProgress); - } -} + flushRenderPhaseStrictModeWarningsInDEV(); -function renderRootConcurrent(root, lanes) { - var prevExecutionContext = executionContext; - executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(); - var prevCacheDispatcher = pushCacheDispatcher(); // If the root or lanes have changed, throw out the existing stack - // and prepare a fresh one. Otherwise we'll continue where we left off. + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error("Should not already be working."); + } - if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { - { - if (isDevToolsPresent) { - var memoizedUpdaters = root.memoizedUpdaters; + var finishedWork = root.finishedWork; + var lanes = root.finishedLanes; - if (memoizedUpdaters.size > 0) { - restorePendingUpdaters(root, workInProgressRootRenderLanes); - memoizedUpdaters.clear(); - } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set. - // If we bailout on this work, we'll move them back (like above). - // It's important to move them now in case the work spawns more work at the same priority with different updaters. - // That way we can keep the current update and future updates separate. + { + if (enableDebugTracing) { + logCommitStarted(lanes); + } + } - movePendingFibersToMemoized(root, lanes); + if (enableSchedulingProfiler) { + markCommitStarted(lanes); } - } - workInProgressTransitions = getTransitionsForLanes(root, lanes); - resetRenderTimer(); - prepareFreshStack(root, lanes); - } + if (finishedWork === null) { + { + if (enableDebugTracing) { + logCommitStopped(); + } + } + + if (enableSchedulingProfiler) { + markCommitStopped(); + } - { - if (enableDebugTracing) { - logRenderStarted(lanes); - } - } + return null; + } else { + { + if (lanes === NoLanes) { + error( + "root.finishedLanes should not be empty during a commit. This is a " + + "bug in React." + ); + } + } + } - if (enableSchedulingProfiler) { - markRenderStarted(lanes); - } + root.finishedWork = null; + root.finishedLanes = NoLanes; + + if (finishedWork === root.current) { + throw new Error( + "Cannot commit the same tree as before. This error is likely caused by " + + "a bug in React. Please file an issue." + ); + } // commitRoot never returns a continuation; it always finishes synchronously. + // So we can clear these now to allow a new callback to be scheduled. + + root.callbackNode = null; + root.callbackPriority = NoLane; + root.cancelPendingCommit = null; // Check which lanes no longer have any work scheduled on them, and mark + // those as finished. + + var remainingLanes = mergeLanes( + finishedWork.lanes, + finishedWork.childLanes + ); // Make sure to account for lanes that were updated by a concurrent event + // during the render phase; don't mark them as finished. + + var concurrentlyUpdatedLanes = getConcurrentlyUpdatedLanes(); + remainingLanes = mergeLanes(remainingLanes, concurrentlyUpdatedLanes); + markRootFinished(root, remainingLanes, spawnedLane); + + if (root === workInProgressRoot) { + // We can reset these now that they are finished. + workInProgressRoot = null; + workInProgress = null; + workInProgressRootRenderLanes = NoLanes; + } // If there are pending passive effects, schedule a callback to process them. + // Do this as early as possible, so it is queued before anything else that + // might get scheduled in the commit phase. (See #16714.) + // TODO: Delete all other places that schedule the passive effect callback + // They're redundant. - outer: do { - try { if ( - workInProgressSuspendedReason !== NotSuspended && - workInProgress !== null + (finishedWork.subtreeFlags & PassiveMask) !== NoFlags$1 || + (finishedWork.flags & PassiveMask) !== NoFlags$1 ) { - // The work loop is suspended. We need to either unwind the stack or - // replay the suspended component. - var unitOfWork = workInProgress; - var thrownValue = workInProgressThrownValue; - - resumeOrUnwind: switch (workInProgressSuspendedReason) { - case SuspendedOnError: { - // Unwind then continue with the normal work loop. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); - break; - } + if (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + pendingPassiveEffectsRemainingLanes = remainingLanes; // workInProgressTransitions might be overwritten, so we want + // to store it in pendingPassiveTransitions until they get processed + // We need to pass this through as an argument to commitRoot + // because workInProgressTransitions might have changed between + // the previous render and commit if we throttle the commit + // with setTimeout + + pendingPassiveTransitions = transitions; + scheduleCallback(NormalPriority$1, function () { + flushPassiveEffects(); // This render triggered passive effects: release the root cache pool + // *after* passive effects fire to avoid freeing a cache pool that may + // be referenced by a node in the tree (HostRoot, Cache boundary etc) - case SuspendedOnData: { - var thenable = thrownValue; + return null; + }); + } + } // Check if there are any effects in the whole tree. + // TODO: This is left over from the effect list implementation, where we had + // to check for the existence of `firstEffect` to satisfy Flow. I think the + // only other reason this optimization exists is because it affects profiling. + // Reconsider whether this is necessary. + + var subtreeHasEffects = + (finishedWork.subtreeFlags & + (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== + NoFlags$1; + var rootHasEffect = + (finishedWork.flags & + (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== + NoFlags$1; + + if (subtreeHasEffects || rootHasEffect) { + var prevTransition = ReactCurrentBatchConfig.transition; + ReactCurrentBatchConfig.transition = null; + var previousPriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority(DiscreteEventPriority); + var prevExecutionContext = executionContext; + executionContext |= CommitContext; // Reset this to null before calling lifecycles + + ReactCurrentOwner.current = null; // The commit phase is broken into several sub-phases. We do a separate pass + // of the effect list for each phase: all mutation effects come before all + // layout effects, and so on. + // The first phase a "before mutation" phase. We use this phase to read the + // state of the host tree right before we mutate it. This is where + // getSnapshotBeforeUpdate is called. + + commitBeforeMutationEffects(root, finishedWork); - if (isThenableResolved(thenable)) { - // The data resolved. Try rendering the component again. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - replaySuspendedUnitOfWork(unitOfWork); - break; - } // The work loop is suspended on data. We should wait for it to - // resolve before continuing to render. - // TODO: Handle the case where the promise resolves synchronously. - // Usually this is handled when we instrument the promise to add a - // `status` field, but if the promise already has a status, we won't - // have added a listener until right here. - - var onResolution = function () { - // Check if the root is still suspended on this promise. - if ( - workInProgressSuspendedReason === SuspendedOnData && - workInProgressRoot === root - ) { - // Mark the root as ready to continue rendering. - workInProgressSuspendedReason = SuspendedAndReadyToContinue; - } // Ensure the root is scheduled. We should do this even if we're - // currently working on a different root, so that we resume - // rendering later. + { + // Mark the current commit time to be shared by all Profilers in this + // batch. This enables them to be grouped later. + recordCommitTime(); + } - ensureRootIsScheduled(root); - }; + if (enableProfilerNestedUpdateScheduledHook) { + // Track the root here, rather than in commitLayoutEffects(), because of ref setters. + // Updates scheduled during ref detachment should also be flagged. + rootCommittingMutationOrLayoutEffects = root; + } // The next phase is the mutation phase, where we mutate the host tree. - thenable.then(onResolution, onResolution); - break outer; - } + commitMutationEffects(root, finishedWork, lanes); + // the mutation phase, so that the previous tree is still current during + // componentWillUnmount, but before the layout phase, so that the finished + // work is current during componentDidMount/Update. - case SuspendedOnImmediate: { - // If this fiber just suspended, it's possible the data is already - // cached. Yield to the main thread to give it a chance to ping. If - // it does, we can retry immediately without unwinding the stack. - workInProgressSuspendedReason = SuspendedAndReadyToContinue; - break outer; - } + root.current = finishedWork; // The next phase is the layout phase, where we call effects that read + // the host tree after it's been mutated. The idiomatic use case for this is + // layout, but class component lifecycles also fire here for legacy reasons. - case SuspendedOnInstance: { - workInProgressSuspendedReason = - SuspendedOnInstanceAndReadyToContinue; - break outer; + { + if (enableDebugTracing) { + logLayoutEffectsStarted(lanes); } + } - case SuspendedAndReadyToContinue: { - var _thenable = thrownValue; + if (enableSchedulingProfiler) { + markLayoutEffectsStarted(lanes); + } - if (isThenableResolved(_thenable)) { - // The data resolved. Try rendering the component again. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - replaySuspendedUnitOfWork(unitOfWork); - } else { - // Otherwise, unwind then continue with the normal work loop. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); - } + commitLayoutEffects(finishedWork, root, lanes); - break; + { + if (enableDebugTracing) { + logLayoutEffectsStopped(); } + } - case SuspendedOnInstanceAndReadyToContinue: { - switch (workInProgress.tag) { - case HostComponent: - case HostHoistable: - case HostSingleton: { - // Before unwinding the stack, check one more time if the - // instance is ready. It may have loaded when React yielded to - // the main thread. - // Assigning this to a constant so Flow knows the binding won't - // be mutated by `preloadInstance`. - var hostFiber = workInProgress; - var type = hostFiber.type; - var props = hostFiber.pendingProps; - var isReady = preloadInstance(type, props); - - if (isReady) { - // The data resolved. Resume the work loop as if nothing - // suspended. Unlike when a user component suspends, we don't - // have to replay anything because the host fiber - // already completed. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - var sibling = hostFiber.sibling; + if (enableSchedulingProfiler) { + markLayoutEffectsStopped(); + } - if (sibling !== null) { - workInProgress = sibling; - } else { - var returnFiber = hostFiber.return; + if (enableProfilerNestedUpdateScheduledHook) { + rootCommittingMutationOrLayoutEffects = null; + } // Tell Scheduler to yield at the end of the frame, so the browser has an + // opportunity to paint. - if (returnFiber !== null) { - workInProgress = returnFiber; - completeUnitOfWork(returnFiber); - } else { - workInProgress = null; - } - } + requestPaint(); + executionContext = prevExecutionContext; // Reset the priority to the previous non-sync value. - break resumeOrUnwind; - } + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig.transition = prevTransition; + } else { + // No effects. + root.current = finishedWork; // Measure these anyway so the flamegraph explicitly shows that there were + // no effects. + // TODO: Maybe there's a better way to report this. - break; - } + { + recordCommitTime(); + } + } - default: { - // This will fail gracefully but it's not correct, so log a - // warning in dev. - if (true) { - error( - "Unexpected type of fiber triggered a suspensey commit. " + - "This is a bug in React." - ); - } + var rootDidHavePassiveEffects = rootDoesHavePassiveEffects; - break; - } - } // Otherwise, unwind then continue with the normal work loop. + if (rootDoesHavePassiveEffects) { + // This commit has passive effects. Stash a reference to them. But don't + // schedule a callback until after flushing layout work. + rootDoesHavePassiveEffects = false; + rootWithPendingPassiveEffects = root; + pendingPassiveEffectsLanes = lanes; + } else { + // There were no passive effects, so we can immediately release the cache + // pool for this render. + releaseRootPooledCache(root, remainingLanes); - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); - break; - } + { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = null; + } + } // Read this again, since an effect might have updated it - case SuspendedOnDeprecatedThrowPromise: { - // Suspended by an old implementation that uses the `throw promise` - // pattern. The newer replaying behavior can cause subtle issues - // like infinite ping loops. So we maintain the old behavior and - // always unwind. - workInProgressSuspendedReason = NotSuspended; - workInProgressThrownValue = null; - throwAndUnwindWorkLoop(unitOfWork, thrownValue); - break; - } + remainingLanes = root.pendingLanes; // Check if there's remaining work on this root + // TODO: This is part of the `componentDidCatch` implementation. Its purpose + // is to detect whether something might have called setState inside + // `componentDidCatch`. The mechanism is known to be flawed because `setState` + // inside `componentDidCatch` is itself flawed — that's why we recommend + // `getDerivedStateFromError` instead. However, it could be improved by + // checking if remainingLanes includes Sync work, instead of whether there's + // any work remaining at all (which would also include stuff like Suspense + // retries or transitions). It's been like this for a while, though, so fixing + // it probably isn't that urgent. - case SuspendedOnHydration: { - // Selective hydration. An update flowed into a dehydrated tree. - // Interrupt the current render so the work loop can switch to the - // hydration lane. - resetWorkInProgressStack(); - workInProgressRootExitStatus = RootDidNotComplete; - break outer; - } + if (remainingLanes === NoLanes) { + // If there's no remaining work, we can clear the set of already failed + // error boundaries. + legacyErrorBoundariesThatAlreadyFailed = null; + } - default: { - throw new Error( - "Unexpected SuspendedReason. This is a bug in React." - ); - } + { + if (!rootDidHavePassiveEffects) { + commitDoubleInvokeEffectsInDEV(root, false); } } - if (true && ReactCurrentActQueue.current !== null) { - // `act` special case: If we're inside an `act` scope, don't consult - // `shouldYield`. Always keep working until the render is complete. - // This is not just an optimization: in a unit test environment, we - // can't trust the result of `shouldYield`, because the host I/O is - // likely mocked. - workLoopSync(); - } else { - workLoopConcurrent(); + onCommitRoot(finishedWork.stateNode, renderPriorityLevel); + + { + if (isDevToolsPresent) { + root.memoizedUpdaters.clear(); + } } + // additional work on this root is scheduled. - break; - } catch (thrownValue) { - handleThrow(root, thrownValue); - } - } while (true); + ensureRootIsScheduled(root); - resetContextDependencies(); - popDispatcher(prevDispatcher); - popCacheDispatcher(prevCacheDispatcher); - executionContext = prevExecutionContext; + if (recoverableErrors !== null) { + // There were errors during this render, but recovered from them without + // needing to surface it to the UI. We log them here. + var onRecoverableError = root.onRecoverableError; - { - if (enableDebugTracing) { - logRenderStopped(); - } - } // Check if the tree has completed. + for (var i = 0; i < recoverableErrors.length; i++) { + var recoverableError = recoverableErrors[i]; + var errorInfo = makeErrorInfo( + recoverableError.digest, + recoverableError.stack + ); + onRecoverableError(recoverableError.value, errorInfo); + } + } - if (workInProgress !== null) { - // Still work remaining. - if (enableSchedulingProfiler) { - markRenderYielded(); - } + if (hasUncaughtError) { + hasUncaughtError = false; + var error$1 = firstUncaughtError; + firstUncaughtError = null; + throw error$1; + } // If the passive effects are the result of a discrete render, flush them + // synchronously at the end of the current task so that the result is + // immediately observable. Otherwise, we assume that they are not + // order-dependent and do not need to be observed by external systems, so we + // can wait until after paint. + // TODO: We can optimize this by not scheduling the callback earlier. Since we + // currently schedule the callback in multiple places, will wait until those + // are consolidated. - return RootInProgress; - } else { - // Completed the tree. - if (enableSchedulingProfiler) { - markRenderStopped(); - } // Set this to null to indicate there's no in-progress render. + if ( + includesSyncLane(pendingPassiveEffectsLanes) && + root.tag !== LegacyRoot + ) { + flushPassiveEffects(); + } // Read this again, since a passive effect might have updated it - workInProgressRoot = null; - workInProgressRootRenderLanes = NoLanes; // It's safe to process the queue now that the render phase is complete. + remainingLanes = root.pendingLanes; // Check if this render scheduled a cascading synchronous update. This is a + // heurstic to detect infinite update loops. We are intentionally excluding + // hydration lanes in this check, because render triggered by selective + // hydration is conceptually not an update. - finishQueueingConcurrentUpdates(); // Return the final exit status. + if ( + // Was the finished render the result of an update (not hydration)? + includesSomeLane(lanes, UpdateLanes) && // Did it schedule a sync update? + includesSomeLane(remainingLanes, SyncUpdateLanes) + ) { + { + markNestedUpdateScheduled(); + } // Count the number of times the root synchronously re-renders without + // finishing. If there are too many, it indicates an infinite update loop. - return workInProgressRootExitStatus; - } -} -/** @noinline */ - -function workLoopConcurrent() { - // Perform work until Scheduler asks us to yield - while (workInProgress !== null && !shouldYield()) { - // $FlowFixMe[incompatible-call] found when upgrading Flow - performUnitOfWork(workInProgress); - } -} + if (root === rootWithNestedUpdates) { + nestedUpdateCount++; + } else { + nestedUpdateCount = 0; + rootWithNestedUpdates = root; + } + } else { + nestedUpdateCount = 0; + } // If layout work was scheduled, flush it now. -function performUnitOfWork(unitOfWork) { - // The current, flushed, state of this fiber is the alternate. Ideally - // nothing should rely on this, but relying on it here means that we don't - // need an additional field on the work in progress. - var current = unitOfWork.alternate; - setCurrentFiber(unitOfWork); - var next; - - if ((unitOfWork.mode & ProfileMode) !== NoMode) { - startProfilerTimer(unitOfWork); - next = beginWork(current, unitOfWork, entangledRenderLanes); - stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); - } else { - next = beginWork(current, unitOfWork, entangledRenderLanes); - } - - resetCurrentFiber(); - unitOfWork.memoizedProps = unitOfWork.pendingProps; - - if (next === null) { - // If this doesn't spawn new work, complete the current work. - completeUnitOfWork(unitOfWork); - } else { - workInProgress = next; - } - - ReactCurrentOwner.current = null; -} + flushSyncWorkOnAllRoots(); -function replaySuspendedUnitOfWork(unitOfWork) { - // This is a fork of performUnitOfWork specifcally for replaying a fiber that - // just suspended. - // - var current = unitOfWork.alternate; - setCurrentFiber(unitOfWork); - var next; - setCurrentFiber(unitOfWork); - var isProfilingMode = (unitOfWork.mode & ProfileMode) !== NoMode; - - if (isProfilingMode) { - startProfilerTimer(unitOfWork); - } - - switch (unitOfWork.tag) { - case IndeterminateComponent: { - // Because it suspended with `use`, we can assume it's a - // function component. - unitOfWork.tag = FunctionComponent; // Fallthrough to the next branch. - } - - case SimpleMemoComponent: - case FunctionComponent: { - // Resolve `defaultProps`. This logic is copied from `beginWork`. - // TODO: Consider moving this switch statement into that module. Also, - // could maybe use this as an opportunity to say `use` doesn't work with - // `defaultProps` :) - var Component = unitOfWork.type; - var unresolvedProps = unitOfWork.pendingProps; - var resolvedProps = - unitOfWork.elementType === Component - ? unresolvedProps - : resolveDefaultProps(Component, unresolvedProps); - var context; + { + if (enableDebugTracing) { + logCommitStopped(); + } + } - next = replayFunctionComponent( - current, - unitOfWork, - resolvedProps, - Component, - context, - workInProgressRootRenderLanes - ); - break; - } + if (enableSchedulingProfiler) { + markCommitStopped(); + } - case ForwardRef: { - // Resolve `defaultProps`. This logic is copied from `beginWork`. - // TODO: Consider moving this switch statement into that module. Also, - // could maybe use this as an opportunity to say `use` doesn't work with - // `defaultProps` :) - var _Component = unitOfWork.type.render; - var _unresolvedProps = unitOfWork.pendingProps; + return null; + } - var _resolvedProps = - unitOfWork.elementType === _Component - ? _unresolvedProps - : resolveDefaultProps(_Component, _unresolvedProps); + function makeErrorInfo(digest, componentStack) { + { + var errorInfo = { + componentStack: componentStack, + digest: digest + }; + Object.defineProperty(errorInfo, "digest", { + configurable: false, + enumerable: true, + get: function () { + error( + 'You are accessing "digest" from the errorInfo object passed to onRecoverableError.' + + " This property is deprecated and will be removed in a future version of React." + + " To access the digest of an Error look for this property on the Error instance itself." + ); - next = replayFunctionComponent( - current, - unitOfWork, - _resolvedProps, - _Component, - unitOfWork.ref, - workInProgressRootRenderLanes - ); - break; + return digest; + } + }); + return errorInfo; + } } - case HostComponent: { - // Some host components are stateful (that's how we implement form - // actions) but we don't bother to reuse the memoized state because it's - // not worth the extra code. The main reason to reuse the previous hooks - // is to reuse uncached promises, but we happen to know that the only - // promises that a host component might suspend on are definitely cached - // because they are controlled by us. So don't bother. - resetHooksOnUnwind(unitOfWork); // Fallthrough to the next branch. - } + function releaseRootPooledCache(root, remainingLanes) { + { + var pooledCacheLanes = (root.pooledCacheLanes &= remainingLanes); - default: { - // Other types besides function components are reset completely before - // being replayed. Currently this only happens when a Usable type is - // reconciled — the reconciler will suspend. - // - // We reset the fiber back to its original state; however, this isn't - // a full "unwind" because we're going to reuse the promises that were - // reconciled previously. So it's intentional that we don't call - // resetSuspendedWorkLoopOnUnwind here. - unwindInterruptedWork(current, unitOfWork); - unitOfWork = workInProgress = resetWorkInProgress( - unitOfWork, - entangledRenderLanes - ); - next = beginWork(current, unitOfWork, entangledRenderLanes); - break; + if (pooledCacheLanes === NoLanes) { + // None of the remaining work relies on the cache pool. Clear it so + // subsequent requests get a new cache + var pooledCache = root.pooledCache; + + if (pooledCache != null) { + root.pooledCache = null; + releaseCache(pooledCache); + } + } + } } - } - if (isProfilingMode) { - stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); - } // The begin phase finished successfully without suspending. Return to the - // normal work loop. + function flushPassiveEffects() { + // Returns whether passive effects were flushed. + // TODO: Combine this check with the one in flushPassiveEFfectsImpl. We should + // probably just combine the two functions. I believe they were only separate + // in the first place because we used to wrap it with + // `Scheduler.runWithPriority`, which accepts a function. But now we track the + // priority within React itself, so we can mutate the variable directly. + if (rootWithPendingPassiveEffects !== null) { + // Cache the root since rootWithPendingPassiveEffects is cleared in + // flushPassiveEffectsImpl + var root = rootWithPendingPassiveEffects; // Cache and clear the remaining lanes flag; it must be reset since this + // method can be called from various places, not always from commitRoot + // where the remaining lanes are known - resetCurrentFiber(); - unitOfWork.memoizedProps = unitOfWork.pendingProps; + var remainingLanes = pendingPassiveEffectsRemainingLanes; + pendingPassiveEffectsRemainingLanes = NoLanes; + var renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes); + var priority = lowerEventPriority(DefaultEventPriority, renderPriority); + var prevTransition = ReactCurrentBatchConfig.transition; + var previousPriority = getCurrentUpdatePriority(); - if (next === null) { - // If this doesn't spawn new work, complete the current work. - completeUnitOfWork(unitOfWork); - } else { - workInProgress = next; - } + try { + ReactCurrentBatchConfig.transition = null; + setCurrentUpdatePriority(priority); + return flushPassiveEffectsImpl(); + } finally { + setCurrentUpdatePriority(previousPriority); + ReactCurrentBatchConfig.transition = prevTransition; // Once passive effects have run for the tree - giving components a + // chance to retain cache instances they use - release the pooled + // cache at the root (if there is one) - ReactCurrentOwner.current = null; -} + releaseRootPooledCache(root, remainingLanes); + } + } -function throwAndUnwindWorkLoop(unitOfWork, thrownValue) { - // This is a fork of performUnitOfWork specifcally for unwinding a fiber - // that threw an exception. - // - // Return to the normal work loop. This will unwind the stack, and potentially - // result in showing a fallback. - resetSuspendedWorkLoopOnUnwind(unitOfWork); - var returnFiber = unitOfWork.return; - - if (returnFiber === null || workInProgressRoot === null) { - // Expected to be working on a non-root fiber. This is a fatal error - // because there's no ancestor that can handle it; the root is - // supposed to capture all errors that weren't caught by an error - // boundary. - workInProgressRootExitStatus = RootFatalErrored; - workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next - // sibling, or the parent if there are no siblings. But since the root - // has no siblings nor a parent, we set it to null. Usually this is - // handled by `completeUnitOfWork` or `unwindWork`, but since we're - // intentionally not calling those, we need set it here. - // TODO: Consider calling `unwindWork` to pop the contexts. - - workInProgress = null; - return; - } - - try { - // Find and mark the nearest Suspense or error boundary that can handle - // this "exception". - throwException( - workInProgressRoot, - returnFiber, - unitOfWork, - thrownValue, - workInProgressRootRenderLanes - ); - } catch (error) { - // We had trouble processing the error. An example of this happening is - // when accessing the `componentDidCatch` property of an error boundary - // throws an error. A weird edge case. There's a regression test for this. - // To prevent an infinite loop, bubble the error up to the next parent. - workInProgress = returnFiber; - throw error; - } - - if (unitOfWork.flags & Incomplete) { - // Unwind the stack until we reach the nearest boundary. - unwindUnitOfWork(unitOfWork); - } else { - // Although the fiber suspended, we're intentionally going to commit it in - // an inconsistent state. We can do this safely in cases where we know the - // inconsistent tree will be hidden. - // - // This currently only applies to Legacy Suspense implementation, but we may - // port a version of this to concurrent roots, too, when performing a - // synchronous render. Because that will allow us to mutate the tree as we - // go instead of buffering mutations until the end. Though it's unclear if - // this particular path is how that would be implemented. - completeUnitOfWork(unitOfWork); - } -} + return false; + } + function enqueuePendingPassiveProfilerEffect(fiber) { + { + pendingPassiveProfilerEffects.push(fiber); + + if (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + scheduleCallback(NormalPriority$1, function () { + flushPassiveEffects(); + return null; + }); + } + } + } -function completeUnitOfWork(unitOfWork) { - // Attempt to complete the current unit of work, then move to the next - // sibling. If there are no more siblings, return to the parent fiber. - var completedWork = unitOfWork; + function flushPassiveEffectsImpl() { + if (rootWithPendingPassiveEffects === null) { + return false; + } // Cache and clear the transitions flag - do { - { - if ((completedWork.flags & Incomplete) !== NoFlags$1) { - // NOTE: If we re-enable sibling prerendering in some cases, this branch - // is where we would switch to the unwinding path. - error( - "Internal React error: Expected this fiber to be complete, but " + - "it isn't. It should have been unwound. This is a bug in React." + var transitions = pendingPassiveTransitions; + pendingPassiveTransitions = null; + var root = rootWithPendingPassiveEffects; + var lanes = pendingPassiveEffectsLanes; + rootWithPendingPassiveEffects = null; // TODO: This is sometimes out of sync with rootWithPendingPassiveEffects. + // Figure out why and fix it. It's not causing any known issues (probably + // because it's only used for profiling), but it's a refactor hazard. + + pendingPassiveEffectsLanes = NoLanes; + + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + throw new Error( + "Cannot flush passive effects while already rendering." ); } - } // The current, flushed, state of this fiber is the alternate. Ideally - // nothing should rely on this, but relying on it here means that we don't - // need an additional field on the work in progress. - var current = completedWork.alternate; - var returnFiber = completedWork.return; - setCurrentFiber(completedWork); - var next = void 0; + { + isFlushingPassiveEffects = true; + didScheduleUpdateDuringPassiveEffects = false; + + if (enableDebugTracing) { + logPassiveEffectsStarted(lanes); + } + } + + if (enableSchedulingProfiler) { + markPassiveEffectsStarted(lanes); + } - if ((completedWork.mode & ProfileMode) === NoMode) { - next = completeWork(current, completedWork, entangledRenderLanes); - } else { - startProfilerTimer(completedWork); - next = completeWork(current, completedWork, entangledRenderLanes); // Update render duration assuming we didn't error. + var prevExecutionContext = executionContext; + executionContext |= CommitContext; + commitPassiveUnmountEffects(root.current); + commitPassiveMountEffects(root, root.current, lanes, transitions); // TODO: Move to commitPassiveMountEffects - stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); - } + { + var profilerEffects = pendingPassiveProfilerEffects; + pendingPassiveProfilerEffects = []; - resetCurrentFiber(); + for (var i = 0; i < profilerEffects.length; i++) { + var fiber = profilerEffects[i]; + commitPassiveEffectDurations(root, fiber); + } + } - if (next !== null) { - // Completing this fiber spawned new work. Work on that next. - workInProgress = next; - return; - } + { + if (enableDebugTracing) { + logPassiveEffectsStopped(); + } + } - var siblingFiber = completedWork.sibling; + if (enableSchedulingProfiler) { + markPassiveEffectsStopped(); + } - if (siblingFiber !== null) { - // If there is more work to do in this returnFiber, do that next. - workInProgress = siblingFiber; - return; - } // Otherwise, return to the parent - // $FlowFixMe[incompatible-type] we bail out when we get a null + { + commitDoubleInvokeEffectsInDEV(root, true); + } - completedWork = returnFiber; // Update the next thing we're working on in case something throws. + executionContext = prevExecutionContext; + flushSyncWorkOnAllRoots(); - workInProgress = completedWork; - } while (completedWork !== null); // We've reached the root. + if (enableTransitionTracing) { + var prevPendingTransitionCallbacks = currentPendingTransitionCallbacks; + var prevRootTransitionCallbacks = root.transitionCallbacks; + var prevEndTime = currentEndTime; - if (workInProgressRootExitStatus === RootInProgress) { - workInProgressRootExitStatus = RootCompleted; - } -} + if ( + prevPendingTransitionCallbacks !== null && + prevRootTransitionCallbacks !== null && + prevEndTime !== null + ) { + currentPendingTransitionCallbacks = null; + currentEndTime = null; + scheduleCallback(IdlePriority, function () { + processTransitionCallbacks( + prevPendingTransitionCallbacks, + prevEndTime, + prevRootTransitionCallbacks + ); + }); + } + } -function unwindUnitOfWork(unitOfWork) { - var incompleteWork = unitOfWork; + { + // If additional passive effects were scheduled, increment a counter. If this + // exceeds the limit, we'll fire a warning. + if (didScheduleUpdateDuringPassiveEffects) { + if (root === rootWithPassiveNestedUpdates) { + nestedPassiveUpdateCount++; + } else { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = root; + } + } else { + nestedPassiveUpdateCount = 0; + } - do { - // The current, flushed, state of this fiber is the alternate. Ideally - // nothing should rely on this, but relying on it here means that we don't - // need an additional field on the work in progress. - var current = incompleteWork.alternate; // This fiber did not complete because something threw. Pop values off - // the stack without entering the complete phase. If this is a boundary, - // capture values if possible. + isFlushingPassiveEffects = false; + didScheduleUpdateDuringPassiveEffects = false; + } // TODO: Move to commitPassiveMountEffects - var next = unwindWork(current, incompleteWork); // Because this fiber did not complete, don't reset its lanes. + onPostCommitRoot(root); - if (next !== null) { - // Found a boundary that can handle this exception. Re-renter the - // begin phase. This branch will return us to the normal work loop. - // - // Since we're restarting, remove anything that is not a host effect - // from the effect tag. - next.flags &= HostEffectMask; - workInProgress = next; - return; - } // Keep unwinding until we reach either a boundary or the root. + { + var stateNode = root.current.stateNode; + stateNode.effectDuration = 0; + stateNode.passiveEffectDuration = 0; + } - if ((incompleteWork.mode & ProfileMode) !== NoMode) { - // Record the render duration for the fiber that errored. - stopProfilerTimerIfRunningAndRecordDelta(incompleteWork, false); // Include the time spent working on failed children before continuing. + return true; + } - var actualDuration = incompleteWork.actualDuration; - var child = incompleteWork.child; + function isAlreadyFailedLegacyErrorBoundary(instance) { + return ( + legacyErrorBoundariesThatAlreadyFailed !== null && + legacyErrorBoundariesThatAlreadyFailed.has(instance) + ); + } + function markLegacyErrorBoundaryAsFailed(instance) { + if (legacyErrorBoundariesThatAlreadyFailed === null) { + legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); + } else { + legacyErrorBoundariesThatAlreadyFailed.add(instance); + } + } - while (child !== null) { - // $FlowFixMe[unsafe-addition] addition with possible null/undefined value - actualDuration += child.actualDuration; - child = child.sibling; + function prepareToThrowUncaughtError(error) { + if (!hasUncaughtError) { + hasUncaughtError = true; + firstUncaughtError = error; } + } - incompleteWork.actualDuration = actualDuration; - } // TODO: Once we stop prerendering siblings, instead of resetting the parent - // of the node being unwound, we should be able to reset node itself as we - // unwind the stack. Saves an additional null check. + var onUncaughtError = prepareToThrowUncaughtError; - var returnFiber = incompleteWork.return; + function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { + var errorInfo = createCapturedValueAtFiber(error, sourceFiber); + var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane); + var root = enqueueUpdate(rootFiber, update, SyncLane); - if (returnFiber !== null) { - // Mark the parent fiber as incomplete and clear its subtree flags. - // TODO: Once we stop prerendering siblings, we may be able to get rid of - // the Incomplete flag because unwinding to the nearest boundary will - // happen synchronously. - returnFiber.flags |= Incomplete; - returnFiber.subtreeFlags = NoFlags$1; - returnFiber.deletions = null; - } // NOTE: If we re-enable sibling prerendering in some cases, here we - // would switch to the normal completion path: check if a sibling - // exists, and if so, begin work on it. - // Otherwise, return to the parent - // $FlowFixMe[incompatible-type] we bail out when we get a null + if (root !== null) { + markRootUpdated(root, SyncLane); + ensureRootIsScheduled(root); + } + } - incompleteWork = returnFiber; // Update the next thing we're working on in case something throws. + function captureCommitPhaseError( + sourceFiber, + nearestMountedAncestor, + error$1 + ) { + { + reportUncaughtErrorInDEV(error$1); + setIsRunningInsertionEffect(false); + } - workInProgress = incompleteWork; - } while (incompleteWork !== null); // We've unwound all the way to the root. + if (sourceFiber.tag === HostRoot) { + // Error was thrown at the root. There is no parent, so the root + // itself should capture it. + captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error$1); + return; + } - workInProgressRootExitStatus = RootDidNotComplete; - workInProgress = null; -} + var fiber = nearestMountedAncestor; -function commitRoot(root, recoverableErrors, transitions, spawnedLane) { - // TODO: This no longer makes any sense. We already wrap the mutation and - // layout phases. Should be able to remove. - var previousUpdateLanePriority = getCurrentUpdatePriority(); - var prevTransition = ReactCurrentBatchConfig.transition; + while (fiber !== null) { + if (fiber.tag === HostRoot) { + captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error$1); + return; + } else if (fiber.tag === ClassComponent) { + var ctor = fiber.type; + var instance = fiber.stateNode; - try { - ReactCurrentBatchConfig.transition = null; - setCurrentUpdatePriority(DiscreteEventPriority); - commitRootImpl( - root, - recoverableErrors, - transitions, - previousUpdateLanePriority, - spawnedLane - ); - } finally { - ReactCurrentBatchConfig.transition = prevTransition; - setCurrentUpdatePriority(previousUpdateLanePriority); - } + if ( + typeof ctor.getDerivedStateFromError === "function" || + (typeof instance.componentDidCatch === "function" && + !isAlreadyFailedLegacyErrorBoundary(instance)) + ) { + var errorInfo = createCapturedValueAtFiber(error$1, sourceFiber); + var update = createClassErrorUpdate(fiber, errorInfo, SyncLane); + var root = enqueueUpdate(fiber, update, SyncLane); - return null; -} + if (root !== null) { + markRootUpdated(root, SyncLane); + ensureRootIsScheduled(root); + } -function commitRootImpl( - root, - recoverableErrors, - transitions, - renderPriorityLevel, - spawnedLane -) { - do { - // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which - // means `flushPassiveEffects` will sometimes result in additional - // passive effects. So we need to keep flushing in a loop until there are - // no more pending effects. - // TODO: Might be better if `flushPassiveEffects` did not automatically - // flush synchronous work at the end, to avoid factoring hazards like this. - flushPassiveEffects(); - } while (rootWithPendingPassiveEffects !== null); - - flushRenderPhaseStrictModeWarningsInDEV(); - - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - throw new Error("Should not already be working."); - } - - var finishedWork = root.finishedWork; - var lanes = root.finishedLanes; - - { - if (enableDebugTracing) { - logCommitStarted(lanes); - } - } - - if (enableSchedulingProfiler) { - markCommitStarted(lanes); - } - - if (finishedWork === null) { - { - if (enableDebugTracing) { - logCommitStopped(); - } - } + return; + } + } - if (enableSchedulingProfiler) { - markCommitStopped(); - } + fiber = fiber.return; + } - return null; - } else { - { - if (lanes === NoLanes) { + { error( - "root.finishedLanes should not be empty during a commit. This is a " + - "bug in React." + "Internal React error: Attempted to capture a commit phase error " + + "inside a detached tree. This indicates a bug in React. Potential " + + "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 ); } } - } + function attachPingListener(root, wakeable, lanes) { + // Attach a ping listener + // + // The data might resolve before we have a chance to commit the fallback. Or, + // in the case of a refresh, we'll never commit a fallback. So we need to + // attach a listener now. When it resolves ("pings"), we can decide whether to + // try rendering the tree again. + // + // Only attach a listener if one does not already exist for the lanes + // we're currently rendering (which acts like a "thread ID" here). + // + // We only need to do this in concurrent mode. Legacy Suspense always + // commits fallbacks synchronously, so there are no pings. + var pingCache = root.pingCache; + var threadIDs; + + if (pingCache === null) { + pingCache = root.pingCache = new PossiblyWeakMap(); + threadIDs = new Set(); + pingCache.set(wakeable, threadIDs); + } else { + threadIDs = pingCache.get(wakeable); + + if (threadIDs === undefined) { + threadIDs = new Set(); + pingCache.set(wakeable, threadIDs); + } + } - root.finishedWork = null; - root.finishedLanes = NoLanes; + if (!threadIDs.has(lanes)) { + workInProgressRootDidAttachPingListener = true; // Memoize using the thread ID to prevent redundant listeners. - if (finishedWork === root.current) { - throw new Error( - "Cannot commit the same tree as before. This error is likely caused by " + - "a bug in React. Please file an issue." - ); - } // commitRoot never returns a continuation; it always finishes synchronously. - // So we can clear these now to allow a new callback to be scheduled. - - root.callbackNode = null; - root.callbackPriority = NoLane; - root.cancelPendingCommit = null; // Check which lanes no longer have any work scheduled on them, and mark - // those as finished. - - var remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes); // Make sure to account for lanes that were updated by a concurrent event - // during the render phase; don't mark them as finished. - - var concurrentlyUpdatedLanes = getConcurrentlyUpdatedLanes(); - remainingLanes = mergeLanes(remainingLanes, concurrentlyUpdatedLanes); - markRootFinished(root, remainingLanes, spawnedLane); - - if (root === workInProgressRoot) { - // We can reset these now that they are finished. - workInProgressRoot = null; - workInProgress = null; - workInProgressRootRenderLanes = NoLanes; - } // If there are pending passive effects, schedule a callback to process them. - // Do this as early as possible, so it is queued before anything else that - // might get scheduled in the commit phase. (See #16714.) - // TODO: Delete all other places that schedule the passive effect callback - // They're redundant. - - if ( - (finishedWork.subtreeFlags & PassiveMask) !== NoFlags$1 || - (finishedWork.flags & PassiveMask) !== NoFlags$1 - ) { - if (!rootDoesHavePassiveEffects) { - rootDoesHavePassiveEffects = true; - pendingPassiveEffectsRemainingLanes = remainingLanes; // workInProgressTransitions might be overwritten, so we want - // to store it in pendingPassiveTransitions until they get processed - // We need to pass this through as an argument to commitRoot - // because workInProgressTransitions might have changed between - // the previous render and commit if we throttle the commit - // with setTimeout - - pendingPassiveTransitions = transitions; - scheduleCallback(NormalPriority$1, function () { - flushPassiveEffects(); // This render triggered passive effects: release the root cache pool - // *after* passive effects fire to avoid freeing a cache pool that may - // be referenced by a node in the tree (HostRoot, Cache boundary etc) + threadIDs.add(lanes); + var ping = pingSuspendedRoot.bind(null, root, wakeable, lanes); - return null; - }); - } - } // Check if there are any effects in the whole tree. - // TODO: This is left over from the effect list implementation, where we had - // to check for the existence of `firstEffect` to satisfy Flow. I think the - // only other reason this optimization exists is because it affects profiling. - // Reconsider whether this is necessary. - - var subtreeHasEffects = - (finishedWork.subtreeFlags & - (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== - NoFlags$1; - var rootHasEffect = - (finishedWork.flags & - (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== - NoFlags$1; - - if (subtreeHasEffects || rootHasEffect) { - var prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = null; - var previousPriority = getCurrentUpdatePriority(); - setCurrentUpdatePriority(DiscreteEventPriority); - var prevExecutionContext = executionContext; - executionContext |= CommitContext; // Reset this to null before calling lifecycles - - ReactCurrentOwner.current = null; // The commit phase is broken into several sub-phases. We do a separate pass - // of the effect list for each phase: all mutation effects come before all - // layout effects, and so on. - // The first phase a "before mutation" phase. We use this phase to read the - // state of the host tree right before we mutate it. This is where - // getSnapshotBeforeUpdate is called. - - commitBeforeMutationEffects(root, finishedWork); + { + if (isDevToolsPresent) { + // If we have pending work still, restore the original updaters + restorePendingUpdaters(root, lanes); + } + } - { - // Mark the current commit time to be shared by all Profilers in this - // batch. This enables them to be grouped later. - recordCommitTime(); + wakeable.then(ping, ping); + } } - if (enableProfilerNestedUpdateScheduledHook) { - // Track the root here, rather than in commitLayoutEffects(), because of ref setters. - // Updates scheduled during ref detachment should also be flagged. - rootCommittingMutationOrLayoutEffects = root; - } // The next phase is the mutation phase, where we mutate the host tree. + function pingSuspendedRoot(root, wakeable, pingedLanes) { + var pingCache = root.pingCache; - commitMutationEffects(root, finishedWork, lanes); - // the mutation phase, so that the previous tree is still current during - // componentWillUnmount, but before the layout phase, so that the finished - // work is current during componentDidMount/Update. + if (pingCache !== null) { + // The wakeable resolved, so we no longer need to memoize, because it will + // never be thrown again. + pingCache.delete(wakeable); + } - root.current = finishedWork; // The next phase is the layout phase, where we call effects that read - // the host tree after it's been mutated. The idiomatic use case for this is - // layout, but class component lifecycles also fire here for legacy reasons. + markRootPinged(root, pingedLanes); + warnIfSuspenseResolutionNotWrappedWithActDEV(root); - { - if (enableDebugTracing) { - logLayoutEffectsStarted(lanes); + if ( + workInProgressRoot === root && + isSubsetOfLanes(workInProgressRootRenderLanes, pingedLanes) + ) { + // Received a ping at the same priority level at which we're currently + // rendering. We might want to restart this render. This should mirror + // the logic of whether or not a root suspends once it completes. + // TODO: If we're rendering sync either due to Sync, Batched or expired, + // we should probably never restart. + // If we're suspended with delay, or if it's a retry, we'll always suspend + // so we can always restart. + if ( + workInProgressRootExitStatus === RootSuspendedWithDelay || + (workInProgressRootExitStatus === RootSuspended && + includesOnlyRetries(workInProgressRootRenderLanes) && + now$1() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) + ) { + // Force a restart from the root by unwinding the stack. Unless this is + // being called from the render phase, because that would cause a crash. + if ((executionContext & RenderContext) === NoContext) { + prepareFreshStack(root, NoLanes); + } + } else { + // Even though we can't restart right now, we might get an + // opportunity later. So we mark this render as having a ping. + workInProgressRootPingedLanes = mergeLanes( + workInProgressRootPingedLanes, + pingedLanes + ); + } } - } - if (enableSchedulingProfiler) { - markLayoutEffectsStarted(lanes); + ensureRootIsScheduled(root); } - commitLayoutEffects(finishedWork, root, lanes); + function retryTimedOutBoundary(boundaryFiber, retryLane) { + // The boundary fiber (a Suspense component or SuspenseList component) + // previously was rendered in its fallback state. One of the promises that + // suspended it has resolved, which means at least part of the tree was + // likely unblocked. Try rendering again, at a new lanes. + if (retryLane === NoLane) { + // TODO: Assign this to `suspenseState.retryLane`? to avoid + // unnecessary entanglement? + retryLane = requestRetryLane(boundaryFiber); + } // TODO: Special case idle priority? - { - if (enableDebugTracing) { - logLayoutEffectsStopped(); + var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); + + if (root !== null) { + markRootUpdated(root, retryLane); + ensureRootIsScheduled(root); } } - if (enableSchedulingProfiler) { - markLayoutEffectsStopped(); + function retryDehydratedSuspenseBoundary(boundaryFiber) { + var suspenseState = boundaryFiber.memoizedState; + var retryLane = NoLane; + + if (suspenseState !== null) { + retryLane = suspenseState.retryLane; + } + + retryTimedOutBoundary(boundaryFiber, retryLane); } + function resolveRetryWakeable(boundaryFiber, wakeable) { + var retryLane = NoLane; // Default - if (enableProfilerNestedUpdateScheduledHook) { - rootCommittingMutationOrLayoutEffects = null; - } // Tell Scheduler to yield at the end of the frame, so the browser has an - // opportunity to paint. + var retryCache; - requestPaint(); - executionContext = prevExecutionContext; // Reset the priority to the previous non-sync value. + switch (boundaryFiber.tag) { + case SuspenseComponent: + retryCache = boundaryFiber.stateNode; + var suspenseState = boundaryFiber.memoizedState; - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; - } else { - // No effects. - root.current = finishedWork; // Measure these anyway so the flamegraph explicitly shows that there were - // no effects. - // TODO: Maybe there's a better way to report this. + if (suspenseState !== null) { + retryLane = suspenseState.retryLane; + } - { - recordCommitTime(); - } - } + break; - var rootDidHavePassiveEffects = rootDoesHavePassiveEffects; + case SuspenseListComponent: + retryCache = boundaryFiber.stateNode; + break; - if (rootDoesHavePassiveEffects) { - // This commit has passive effects. Stash a reference to them. But don't - // schedule a callback until after flushing layout work. - rootDoesHavePassiveEffects = false; - rootWithPendingPassiveEffects = root; - pendingPassiveEffectsLanes = lanes; - } else { - // There were no passive effects, so we can immediately release the cache - // pool for this render. - releaseRootPooledCache(root, remainingLanes); + case OffscreenComponent: { + var instance = boundaryFiber.stateNode; + retryCache = instance._retryCache; + break; + } - { - nestedPassiveUpdateCount = 0; - rootWithPassiveNestedUpdates = null; - } - } // Read this again, since an effect might have updated it - - remainingLanes = root.pendingLanes; // Check if there's remaining work on this root - // TODO: This is part of the `componentDidCatch` implementation. Its purpose - // is to detect whether something might have called setState inside - // `componentDidCatch`. The mechanism is known to be flawed because `setState` - // inside `componentDidCatch` is itself flawed — that's why we recommend - // `getDerivedStateFromError` instead. However, it could be improved by - // checking if remainingLanes includes Sync work, instead of whether there's - // any work remaining at all (which would also include stuff like Suspense - // retries or transitions). It's been like this for a while, though, so fixing - // it probably isn't that urgent. - - if (remainingLanes === NoLanes) { - // If there's no remaining work, we can clear the set of already failed - // error boundaries. - legacyErrorBoundariesThatAlreadyFailed = null; - } - - { - if (!rootDidHavePassiveEffects) { - commitDoubleInvokeEffectsInDEV(root, false); - } - } - - onCommitRoot(finishedWork.stateNode, renderPriorityLevel); - - { - if (isDevToolsPresent) { - root.memoizedUpdaters.clear(); - } - } - // additional work on this root is scheduled. - - ensureRootIsScheduled(root); - - if (recoverableErrors !== null) { - // There were errors during this render, but recovered from them without - // needing to surface it to the UI. We log them here. - var onRecoverableError = root.onRecoverableError; - - for (var i = 0; i < recoverableErrors.length; i++) { - var recoverableError = recoverableErrors[i]; - var errorInfo = makeErrorInfo( - recoverableError.digest, - recoverableError.stack - ); - onRecoverableError(recoverableError.value, errorInfo); - } - } - - if (hasUncaughtError) { - hasUncaughtError = false; - var error$1 = firstUncaughtError; - firstUncaughtError = null; - throw error$1; - } // If the passive effects are the result of a discrete render, flush them - // synchronously at the end of the current task so that the result is - // immediately observable. Otherwise, we assume that they are not - // order-dependent and do not need to be observed by external systems, so we - // can wait until after paint. - // TODO: We can optimize this by not scheduling the callback earlier. Since we - // currently schedule the callback in multiple places, will wait until those - // are consolidated. - - if (includesSyncLane(pendingPassiveEffectsLanes) && root.tag !== LegacyRoot) { - flushPassiveEffects(); - } // Read this again, since a passive effect might have updated it - - remainingLanes = root.pendingLanes; // Check if this render scheduled a cascading synchronous update. This is a - // heurstic to detect infinite update loops. We are intentionally excluding - // hydration lanes in this check, because render triggered by selective - // hydration is conceptually not an update. - - if ( - // Was the finished render the result of an update (not hydration)? - includesSomeLane(lanes, UpdateLanes) && // Did it schedule a sync update? - includesSomeLane(remainingLanes, SyncUpdateLanes) - ) { - { - markNestedUpdateScheduled(); - } // Count the number of times the root synchronously re-renders without - // finishing. If there are too many, it indicates an infinite update loop. + default: + throw new Error( + "Pinged unknown suspense boundary type. " + + "This is probably a bug in React." + ); + } - if (root === rootWithNestedUpdates) { - nestedUpdateCount++; - } else { - nestedUpdateCount = 0; - rootWithNestedUpdates = root; + if (retryCache !== null) { + // The wakeable resolved, so we no longer need to memoize, because it will + // never be thrown again. + retryCache.delete(wakeable); + } + + retryTimedOutBoundary(boundaryFiber, retryLane); } - } else { - nestedUpdateCount = 0; - } // If layout work was scheduled, flush it now. + function throwIfInfiniteUpdateLoopDetected() { + if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { + nestedUpdateCount = 0; + nestedPassiveUpdateCount = 0; + rootWithNestedUpdates = null; + rootWithPassiveNestedUpdates = null; + 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." + ); + } - flushSyncWorkOnAllRoots(); + { + if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { + nestedPassiveUpdateCount = 0; + rootWithPassiveNestedUpdates = null; - { - if (enableDebugTracing) { - logCommitStopped(); + 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." + ); + } + } } - } - if (enableSchedulingProfiler) { - markCommitStopped(); - } + function flushRenderPhaseStrictModeWarningsInDEV() { + { + ReactStrictModeWarnings.flushLegacyContextWarning(); + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); + } + } - return null; -} + function commitDoubleInvokeEffectsInDEV(root, hasPassiveEffects) { + { + { + legacyCommitDoubleInvokeEffectsInDEV(root.current, hasPassiveEffects); + } + } + } -function makeErrorInfo(digest, componentStack) { - { - var errorInfo = { - componentStack: componentStack, - digest: digest - }; - Object.defineProperty(errorInfo, "digest", { - configurable: false, - enumerable: true, - get: function () { - error( - 'You are accessing "digest" from the errorInfo object passed to onRecoverableError.' + - " This property is deprecated and will be removed in a future version of React." + - " To access the digest of an Error look for this property on the Error instance itself." - ); + function legacyCommitDoubleInvokeEffectsInDEV(fiber, hasPassiveEffects) { + // TODO (StrictEffects) Should we set a marker on the root if it contains strict effects + // so we don't traverse unnecessarily? similar to subtreeFlags but just at the root level. + // Maybe not a big deal since this is DEV only behavior. + setCurrentFiber(fiber); + invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectUnmountInDEV); - return digest; + if (hasPassiveEffects) { + invokeEffectsInDev( + fiber, + MountPassiveDev, + invokePassiveEffectUnmountInDEV + ); } - }); - return errorInfo; - } -} - -function releaseRootPooledCache(root, remainingLanes) { - { - var pooledCacheLanes = (root.pooledCacheLanes &= remainingLanes); - if (pooledCacheLanes === NoLanes) { - // None of the remaining work relies on the cache pool. Clear it so - // subsequent requests get a new cache - var pooledCache = root.pooledCache; + invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectMountInDEV); - if (pooledCache != null) { - root.pooledCache = null; - releaseCache(pooledCache); + if (hasPassiveEffects) { + invokeEffectsInDev( + fiber, + MountPassiveDev, + invokePassiveEffectMountInDEV + ); } + + resetCurrentFiber(); } - } -} -function flushPassiveEffects() { - // Returns whether passive effects were flushed. - // TODO: Combine this check with the one in flushPassiveEFfectsImpl. We should - // probably just combine the two functions. I believe they were only separate - // in the first place because we used to wrap it with - // `Scheduler.runWithPriority`, which accepts a function. But now we track the - // priority within React itself, so we can mutate the variable directly. - if (rootWithPendingPassiveEffects !== null) { - // Cache the root since rootWithPendingPassiveEffects is cleared in - // flushPassiveEffectsImpl - var root = rootWithPendingPassiveEffects; // Cache and clear the remaining lanes flag; it must be reset since this - // method can be called from various places, not always from commitRoot - // where the remaining lanes are known - - var remainingLanes = pendingPassiveEffectsRemainingLanes; - pendingPassiveEffectsRemainingLanes = NoLanes; - var renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes); - var priority = lowerEventPriority(DefaultEventPriority, renderPriority); - var prevTransition = ReactCurrentBatchConfig.transition; - var previousPriority = getCurrentUpdatePriority(); - - try { - ReactCurrentBatchConfig.transition = null; - setCurrentUpdatePriority(priority); - return flushPassiveEffectsImpl(); - } finally { - setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; // Once passive effects have run for the tree - giving components a - // chance to retain cache instances they use - release the pooled - // cache at the root (if there is one) - - releaseRootPooledCache(root, remainingLanes); - } - } - - return false; -} -function enqueuePendingPassiveProfilerEffect(fiber) { - { - pendingPassiveProfilerEffects.push(fiber); + function invokeEffectsInDev(firstChild, fiberFlags, invokeEffectFn) { + var current = firstChild; + var subtreeRoot = null; - if (!rootDoesHavePassiveEffects) { - rootDoesHavePassiveEffects = true; - scheduleCallback(NormalPriority$1, function () { - flushPassiveEffects(); - return null; - }); + while (current != null) { + var primarySubtreeFlag = current.subtreeFlags & fiberFlags; + + if ( + current !== subtreeRoot && + current.child != null && + primarySubtreeFlag !== NoFlags$1 + ) { + current = current.child; + } else { + if ((current.flags & fiberFlags) !== NoFlags$1) { + invokeEffectFn(current); + } + + if (current.sibling !== null) { + current = current.sibling; + } else { + current = subtreeRoot = current.return; + } + } + } } - } -} -function flushPassiveEffectsImpl() { - if (rootWithPendingPassiveEffects === null) { - return false; - } // Cache and clear the transitions flag + var didWarnStateUpdateForNotYetMountedComponent = null; + function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { + { + if ((executionContext & RenderContext) !== NoContext) { + // We let the other warning about render phase updates deal with this one. + return; + } - var transitions = pendingPassiveTransitions; - pendingPassiveTransitions = null; - var root = rootWithPendingPassiveEffects; - var lanes = pendingPassiveEffectsLanes; - rootWithPendingPassiveEffects = null; // TODO: This is sometimes out of sync with rootWithPendingPassiveEffects. - // Figure out why and fix it. It's not causing any known issues (probably - // because it's only used for profiling), but it's a refactor hazard. + if (!(fiber.mode & ConcurrentMode)) { + return; + } - pendingPassiveEffectsLanes = NoLanes; + var tag = fiber.tag; - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - throw new Error("Cannot flush passive effects while already rendering."); - } + if ( + tag !== IndeterminateComponent && + tag !== HostRoot && + tag !== ClassComponent && + tag !== FunctionComponent && + tag !== ForwardRef && + tag !== MemoComponent && + tag !== SimpleMemoComponent + ) { + // Only warn for user-defined components, not internal ones like Suspense. + return; + } // We show the whole stack but dedupe on the top component's name because + // the problematic code almost always lies inside that component. - { - isFlushingPassiveEffects = true; - didScheduleUpdateDuringPassiveEffects = false; + var componentName = + getComponentNameFromFiber(fiber) || "ReactComponent"; - if (enableDebugTracing) { - logPassiveEffectsStarted(lanes); - } - } + if (didWarnStateUpdateForNotYetMountedComponent !== null) { + if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) { + return; + } // $FlowFixMe[incompatible-use] found when upgrading Flow - if (enableSchedulingProfiler) { - markPassiveEffectsStarted(lanes); - } + didWarnStateUpdateForNotYetMountedComponent.add(componentName); + } else { + didWarnStateUpdateForNotYetMountedComponent = new Set([ + componentName + ]); + } - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - commitPassiveUnmountEffects(root.current); - commitPassiveMountEffects(root, root.current, lanes, transitions); // TODO: Move to commitPassiveMountEffects + var previousFiber = current; - { - var profilerEffects = pendingPassiveProfilerEffects; - pendingPassiveProfilerEffects = []; + try { + setCurrentFiber(fiber); - for (var i = 0; i < profilerEffects.length; i++) { - var fiber = profilerEffects[i]; - commitPassiveEffectDurations(root, fiber); + 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." + ); + } finally { + if (previousFiber) { + setCurrentFiber(fiber); + } else { + resetCurrentFiber(); + } + } + } } - } + var beginWork; - { - if (enableDebugTracing) { - logPassiveEffectsStopped(); - } - } + if (replayFailedUnitOfWorkWithInvokeGuardedCallback) { + var dummyFiber = null; - if (enableSchedulingProfiler) { - markPassiveEffectsStopped(); - } + beginWork = function (current, unitOfWork, lanes) { + // If a component throws an error, we replay it again in a synchronously + // dispatched event, so that the debugger will treat it as an uncaught + // error See ReactErrorUtils for more information. + // Before entering the begin phase, copy the work-in-progress onto a dummy + // fiber. If beginWork throws, we'll use this to reset the state. + var originalWorkInProgressCopy = assignFiberPropertiesInDEV( + dummyFiber, + unitOfWork + ); - { - commitDoubleInvokeEffectsInDEV(root, true); - } + try { + return beginWork$1(current, unitOfWork, lanes); + } catch (originalError) { + if ( + didSuspendOrErrorWhileHydratingDEV() || + originalError === SuspenseException || + originalError === SelectiveHydrationException || + (originalError !== null && + typeof originalError === "object" && + typeof originalError.then === "function") + ) { + // Don't replay promises. + // Don't replay errors if we are hydrating and have already suspended or handled an error + throw originalError; + } // Don't reset current debug fiber, since we're about to work on the + // same fiber again. + // Unwind the failed stack frame - executionContext = prevExecutionContext; - flushSyncWorkOnAllRoots(); + resetSuspendedWorkLoopOnUnwind(unitOfWork); + unwindInterruptedWork(current, unitOfWork); // Restore the original properties of the fiber. - if (enableTransitionTracing) { - var prevPendingTransitionCallbacks = currentPendingTransitionCallbacks; - var prevRootTransitionCallbacks = root.transitionCallbacks; - var prevEndTime = currentEndTime; + assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); - if ( - prevPendingTransitionCallbacks !== null && - prevRootTransitionCallbacks !== null && - prevEndTime !== null - ) { - currentPendingTransitionCallbacks = null; - currentEndTime = null; - scheduleCallback(IdlePriority, function () { - processTransitionCallbacks( - prevPendingTransitionCallbacks, - prevEndTime, - prevRootTransitionCallbacks - ); - }); - } - } + if (unitOfWork.mode & ProfileMode) { + // Reset the profiler timer. + startProfilerTimer(unitOfWork); + } // Run beginWork again. - { - // If additional passive effects were scheduled, increment a counter. If this - // exceeds the limit, we'll fire a warning. - if (didScheduleUpdateDuringPassiveEffects) { - if (root === rootWithPassiveNestedUpdates) { - nestedPassiveUpdateCount++; - } else { - nestedPassiveUpdateCount = 0; - rootWithPassiveNestedUpdates = root; - } - } else { - nestedPassiveUpdateCount = 0; - } + invokeGuardedCallback( + null, + beginWork$1, + null, + current, + unitOfWork, + lanes + ); - isFlushingPassiveEffects = false; - didScheduleUpdateDuringPassiveEffects = false; - } // TODO: Move to commitPassiveMountEffects + if (hasCaughtError()) { + var replayError = clearCaughtError(); - onPostCommitRoot(root); + if ( + typeof replayError === "object" && + replayError !== null && + replayError._suppressLogging && + typeof originalError === "object" && + originalError !== null && + !originalError._suppressLogging + ) { + // If suppressed, let the flag carry over to the original error which is the one we'll rethrow. + originalError._suppressLogging = true; + } + } // We always throw the original error in case the second render pass is not idempotent. + // This can happen if a memoized function or CommonJS module doesn't throw after first invocation. - { - var stateNode = root.current.stateNode; - stateNode.effectDuration = 0; - stateNode.passiveEffectDuration = 0; - } + throw originalError; + } + }; + } else { + beginWork = beginWork$1; + } - return true; -} + var didWarnAboutUpdateInRender = false; + var didWarnAboutUpdateInRenderForAnotherComponent; -function isAlreadyFailedLegacyErrorBoundary(instance) { - return ( - legacyErrorBoundariesThatAlreadyFailed !== null && - legacyErrorBoundariesThatAlreadyFailed.has(instance) - ); -} -function markLegacyErrorBoundaryAsFailed(instance) { - if (legacyErrorBoundariesThatAlreadyFailed === null) { - legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); - } else { - legacyErrorBoundariesThatAlreadyFailed.add(instance); - } -} + { + didWarnAboutUpdateInRenderForAnotherComponent = new Set(); + } -function prepareToThrowUncaughtError(error) { - if (!hasUncaughtError) { - hasUncaughtError = true; - firstUncaughtError = error; - } -} + function warnAboutRenderPhaseUpdatesInDEV(fiber) { + { + if (isRendering) { + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + var renderingComponentName = + (workInProgress && getComponentNameFromFiber(workInProgress)) || + "Unknown"; // Dedupe by the rendering component because it's the one that needs to be fixed. -var onUncaughtError = prepareToThrowUncaughtError; + var dedupeKey = renderingComponentName; -function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { - var errorInfo = createCapturedValueAtFiber(error, sourceFiber); - var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane); - var root = enqueueUpdate(rootFiber, update, SyncLane); + if ( + !didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey) + ) { + didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey); + var setStateComponentName = + getComponentNameFromFiber(fiber) || "Unknown"; - if (root !== null) { - markRootUpdated(root, SyncLane); - ensureRootIsScheduled(root); - } -} + 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 + ); + } -function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error$1) { - { - reportUncaughtErrorInDEV(error$1); - setIsRunningInsertionEffect(false); - } - - if (sourceFiber.tag === HostRoot) { - // Error was thrown at the root. There is no parent, so the root - // itself should capture it. - captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error$1); - return; - } - - var fiber = nearestMountedAncestor; - - while (fiber !== null) { - if (fiber.tag === HostRoot) { - captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error$1); - return; - } else if (fiber.tag === ClassComponent) { - var ctor = fiber.type; - var instance = fiber.stateNode; + break; + } - if ( - typeof ctor.getDerivedStateFromError === "function" || - (typeof instance.componentDidCatch === "function" && - !isAlreadyFailedLegacyErrorBoundary(instance)) - ) { - var errorInfo = createCapturedValueAtFiber(error$1, sourceFiber); - var update = createClassErrorUpdate(fiber, errorInfo, SyncLane); - var root = enqueueUpdate(fiber, update, SyncLane); + case ClassComponent: { + if (!didWarnAboutUpdateInRender) { + error( + "Cannot update during an existing state transition (such as " + + "within `render`). Render methods should be a pure " + + "function of props and state." + ); - if (root !== null) { - markRootUpdated(root, SyncLane); - ensureRootIsScheduled(root); - } + didWarnAboutUpdateInRender = true; + } - return; + break; + } + } + } } } - fiber = fiber.return; - } - - { - error( - "Internal React error: Attempted to capture a commit phase error " + - "inside a detached tree. This indicates a bug in React. Potential " + - "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 - ); - } -} -function attachPingListener(root, wakeable, lanes) { - // Attach a ping listener - // - // The data might resolve before we have a chance to commit the fallback. Or, - // in the case of a refresh, we'll never commit a fallback. So we need to - // attach a listener now. When it resolves ("pings"), we can decide whether to - // try rendering the tree again. - // - // Only attach a listener if one does not already exist for the lanes - // we're currently rendering (which acts like a "thread ID" here). - // - // We only need to do this in concurrent mode. Legacy Suspense always - // commits fallbacks synchronously, so there are no pings. - var pingCache = root.pingCache; - var threadIDs; - - if (pingCache === null) { - pingCache = root.pingCache = new PossiblyWeakMap(); - threadIDs = new Set(); - pingCache.set(wakeable, threadIDs); - } else { - threadIDs = pingCache.get(wakeable); - - if (threadIDs === undefined) { - threadIDs = new Set(); - pingCache.set(wakeable, threadIDs); - } - } - - if (!threadIDs.has(lanes)) { - workInProgressRootDidAttachPingListener = true; // Memoize using the thread ID to prevent redundant listeners. - - threadIDs.add(lanes); - var ping = pingSuspendedRoot.bind(null, root, wakeable, lanes); - - { - if (isDevToolsPresent) { - // If we have pending work still, restore the original updaters - restorePendingUpdaters(root, lanes); + function restorePendingUpdaters(root, lanes) { + { + if (isDevToolsPresent) { + var memoizedUpdaters = root.memoizedUpdaters; + memoizedUpdaters.forEach(function (schedulingFiber) { + addFiberToLanesMap(root, schedulingFiber, lanes); + }); // This function intentionally does not clear memoized updaters. + // Those may still be relevant to the current commit + // and a future one (e.g. Suspense). + } } } + var fakeActCallbackNode = {}; // $FlowFixMe[missing-local-annot] - wakeable.then(ping, ping); - } -} + function scheduleCallback(priorityLevel, callback) { + { + // If we're currently inside an `act` scope, bypass Scheduler and push to + // the `act` queue instead. + var actQueue = ReactCurrentActQueue.current; -function pingSuspendedRoot(root, wakeable, pingedLanes) { - var pingCache = root.pingCache; - - if (pingCache !== null) { - // The wakeable resolved, so we no longer need to memoize, because it will - // never be thrown again. - pingCache.delete(wakeable); - } - - markRootPinged(root, pingedLanes); - warnIfSuspenseResolutionNotWrappedWithActDEV(root); - - if ( - workInProgressRoot === root && - isSubsetOfLanes(workInProgressRootRenderLanes, pingedLanes) - ) { - // Received a ping at the same priority level at which we're currently - // rendering. We might want to restart this render. This should mirror - // the logic of whether or not a root suspends once it completes. - // TODO: If we're rendering sync either due to Sync, Batched or expired, - // we should probably never restart. - // If we're suspended with delay, or if it's a retry, we'll always suspend - // so we can always restart. - if ( - workInProgressRootExitStatus === RootSuspendedWithDelay || - (workInProgressRootExitStatus === RootSuspended && - includesOnlyRetries(workInProgressRootRenderLanes) && - now$1() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) - ) { - // Force a restart from the root by unwinding the stack. Unless this is - // being called from the render phase, because that would cause a crash. - if ((executionContext & RenderContext) === NoContext) { - prepareFreshStack(root, NoLanes); + if (actQueue !== null) { + actQueue.push(callback); + return fakeActCallbackNode; + } else { + return scheduleCallback$3(priorityLevel, callback); + } } - } else { - // Even though we can't restart right now, we might get an - // opportunity later. So we mark this render as having a ping. - workInProgressRootPingedLanes = mergeLanes( - workInProgressRootPingedLanes, - pingedLanes - ); } - } - - ensureRootIsScheduled(root); -} -function retryTimedOutBoundary(boundaryFiber, retryLane) { - // The boundary fiber (a Suspense component or SuspenseList component) - // previously was rendered in its fallback state. One of the promises that - // suspended it has resolved, which means at least part of the tree was - // likely unblocked. Try rendering again, at a new lanes. - if (retryLane === NoLane) { - // TODO: Assign this to `suspenseState.retryLane`? to avoid - // unnecessary entanglement? - retryLane = requestRetryLane(boundaryFiber); - } // TODO: Special case idle priority? - - var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); - - if (root !== null) { - markRootUpdated(root, retryLane); - ensureRootIsScheduled(root); - } -} + function shouldForceFlushFallbacksInDEV() { + // Never force flush in production. This function should get stripped out. + return ReactCurrentActQueue.current !== null; + } -function retryDehydratedSuspenseBoundary(boundaryFiber) { - var suspenseState = boundaryFiber.memoizedState; - var retryLane = NoLane; + function warnIfUpdatesNotWrappedWithActDEV(fiber) { + { + if (fiber.mode & ConcurrentMode) { + if (!isConcurrentActEnvironment()) { + // Not in an act environment. No need to warn. + return; + } + } else { + // Legacy mode has additional cases where we suppress a warning. + if (!isLegacyActEnvironment()) { + // Not in an act environment. No need to warn. + return; + } - if (suspenseState !== null) { - retryLane = suspenseState.retryLane; - } + if (executionContext !== NoContext) { + // Legacy mode doesn't warn if the update is batched, i.e. + // batchedUpdates or flushSync. + return; + } - retryTimedOutBoundary(boundaryFiber, retryLane); -} -function resolveRetryWakeable(boundaryFiber, wakeable) { - var retryLane = NoLane; // Default + if ( + fiber.tag !== FunctionComponent && + fiber.tag !== ForwardRef && + fiber.tag !== SimpleMemoComponent + ) { + // For backwards compatibility with pre-hooks code, legacy mode only + // warns for updates that originate from a hook. + return; + } + } - var retryCache; + if (ReactCurrentActQueue.current === null) { + var previousFiber = current; - switch (boundaryFiber.tag) { - case SuspenseComponent: - retryCache = boundaryFiber.stateNode; - var suspenseState = boundaryFiber.memoizedState; + try { + setCurrentFiber(fiber); - if (suspenseState !== null) { - retryLane = suspenseState.retryLane; + 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) + ); + } finally { + if (previousFiber) { + setCurrentFiber(fiber); + } else { + resetCurrentFiber(); + } + } + } } + } - break; - - case SuspenseListComponent: - retryCache = boundaryFiber.stateNode; - break; + function warnIfSuspenseResolutionNotWrappedWithActDEV(root) { + { + if ( + root.tag !== LegacyRoot && + isConcurrentActEnvironment() && + ReactCurrentActQueue.current === null + ) { + 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" + ); + } + } + } - case OffscreenComponent: { - var instance = boundaryFiber.stateNode; - retryCache = instance._retryCache; - break; + function setIsRunningInsertionEffect(isRunning) { + { + isRunningInsertionEffect = isRunning; + } } - default: - throw new Error( - "Pinged unknown suspense boundary type. " + - "This is probably a bug in React." - ); - } + /* eslint-disable react-internal/prod-error-codes */ + // Used by React Refresh runtime through DevTools Global Hook. - if (retryCache !== null) { - // The wakeable resolved, so we no longer need to memoize, because it will - // never be thrown again. - retryCache.delete(wakeable); - } + var resolveFamily = null; + var failedBoundaries = null; + var setRefreshHandler = function (handler) { + { + resolveFamily = handler; + } + }; + function resolveFunctionForHotReloading(type) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return type; + } - retryTimedOutBoundary(boundaryFiber, retryLane); -} -function throwIfInfiniteUpdateLoopDetected() { - if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { - nestedUpdateCount = 0; - nestedPassiveUpdateCount = 0; - rootWithNestedUpdates = null; - rootWithPassiveNestedUpdates = null; - 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." - ); - } - - { - if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { - nestedPassiveUpdateCount = 0; - rootWithPassiveNestedUpdates = null; - - 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." - ); - } - } -} + var family = resolveFamily(type); -function flushRenderPhaseStrictModeWarningsInDEV() { - { - ReactStrictModeWarnings.flushLegacyContextWarning(); - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); - } -} + if (family === undefined) { + return type; + } // Use the latest known implementation. -function commitDoubleInvokeEffectsInDEV(root, hasPassiveEffects) { - { - { - legacyCommitDoubleInvokeEffectsInDEV(root.current, hasPassiveEffects); + return family.current; + } } - } -} + function resolveClassForHotReloading(type) { + // No implementation differences. + return resolveFunctionForHotReloading(type); + } + function resolveForwardRefForHotReloading(type) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return type; + } -function legacyCommitDoubleInvokeEffectsInDEV(fiber, hasPassiveEffects) { - // TODO (StrictEffects) Should we set a marker on the root if it contains strict effects - // so we don't traverse unnecessarily? similar to subtreeFlags but just at the root level. - // Maybe not a big deal since this is DEV only behavior. - setCurrentFiber(fiber); - invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectUnmountInDEV); + var family = resolveFamily(type); - if (hasPassiveEffects) { - invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectUnmountInDEV); - } + if (family === undefined) { + // Check if we're dealing with a real forwardRef. Don't want to crash early. + if ( + type !== null && + type !== undefined && + typeof type.render === "function" + ) { + // ForwardRef is special because its resolved .type is an object, + // but it's possible that we only have its inner render function in the map. + // If that inner render function is different, we'll build a new forwardRef type. + var currentRender = resolveFunctionForHotReloading(type.render); + + if (type.render !== currentRender) { + var syntheticType = { + $$typeof: REACT_FORWARD_REF_TYPE, + render: currentRender + }; + + if (type.displayName !== undefined) { + syntheticType.displayName = type.displayName; + } - invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectMountInDEV); + return syntheticType; + } + } - if (hasPassiveEffects) { - invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectMountInDEV); - } + return type; + } // Use the latest known implementation. - resetCurrentFiber(); -} + return family.current; + } + } + function isCompatibleFamilyForHotReloading(fiber, element) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return false; + } -function invokeEffectsInDev(firstChild, fiberFlags, invokeEffectFn) { - var current = firstChild; - var subtreeRoot = null; + var prevType = fiber.elementType; + var nextType = element.type; // If we got here, we know types aren't === equal. - while (current != null) { - var primarySubtreeFlag = current.subtreeFlags & fiberFlags; + var needsCompareFamilies = false; + var $$typeofNextType = + typeof nextType === "object" && nextType !== null + ? nextType.$$typeof + : null; - if ( - current !== subtreeRoot && - current.child != null && - primarySubtreeFlag !== NoFlags$1 - ) { - current = current.child; - } else { - if ((current.flags & fiberFlags) !== NoFlags$1) { - invokeEffectFn(current); - } + switch (fiber.tag) { + case ClassComponent: { + if (typeof nextType === "function") { + needsCompareFamilies = true; + } - if (current.sibling !== null) { - current = current.sibling; - } else { - current = subtreeRoot = current.return; - } - } - } -} + break; + } -var didWarnStateUpdateForNotYetMountedComponent = null; -function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { - { - if ((executionContext & RenderContext) !== NoContext) { - // We let the other warning about render phase updates deal with this one. - return; - } + case FunctionComponent: { + if (typeof nextType === "function") { + needsCompareFamilies = true; + } else if ($$typeofNextType === REACT_LAZY_TYPE) { + // We don't know the inner type yet. + // We're going to assume that the lazy inner type is stable, + // and so it is sufficient to avoid reconciling it away. + // We're not going to unwrap or actually use the new lazy type. + needsCompareFamilies = true; + } - if (!(fiber.mode & ConcurrentMode)) { - return; - } + break; + } - var tag = fiber.tag; + case ForwardRef: { + if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { + needsCompareFamilies = true; + } else if ($$typeofNextType === REACT_LAZY_TYPE) { + needsCompareFamilies = true; + } - if ( - tag !== IndeterminateComponent && - tag !== HostRoot && - tag !== ClassComponent && - tag !== FunctionComponent && - tag !== ForwardRef && - tag !== MemoComponent && - tag !== SimpleMemoComponent - ) { - // Only warn for user-defined components, not internal ones like Suspense. - return; - } // We show the whole stack but dedupe on the top component's name because - // the problematic code almost always lies inside that component. + break; + } - var componentName = getComponentNameFromFiber(fiber) || "ReactComponent"; + case MemoComponent: + case SimpleMemoComponent: { + if ($$typeofNextType === REACT_MEMO_TYPE) { + // TODO: if it was but can no longer be simple, + // we shouldn't set this. + needsCompareFamilies = true; + } else if ($$typeofNextType === REACT_LAZY_TYPE) { + needsCompareFamilies = true; + } - if (didWarnStateUpdateForNotYetMountedComponent !== null) { - if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) { - return; - } // $FlowFixMe[incompatible-use] found when upgrading Flow + break; + } - didWarnStateUpdateForNotYetMountedComponent.add(componentName); - } else { - didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]); - } + default: + return false; + } // Check if both types have a family and it's the same one. - var previousFiber = current; + if (needsCompareFamilies) { + // Note: memo() and forwardRef() we'll compare outer rather than inner type. + // This means both of them need to be registered to preserve state. + // If we unwrapped and compared the inner types for wrappers instead, + // then we would risk falsely saying two separate memo(Foo) + // calls are equivalent because they wrap the same Foo function. + var prevFamily = resolveFamily(prevType); // $FlowFixMe[not-a-function] found when upgrading Flow - try { - setCurrentFiber(fiber); + if ( + prevFamily !== undefined && + prevFamily === resolveFamily(nextType) + ) { + return true; + } + } - 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." - ); - } finally { - if (previousFiber) { - setCurrentFiber(fiber); - } else { - resetCurrentFiber(); + return false; } } - } -} -var beginWork; - -if (replayFailedUnitOfWorkWithInvokeGuardedCallback) { - var dummyFiber = null; - - beginWork = function (current, unitOfWork, lanes) { - // If a component throws an error, we replay it again in a synchronously - // dispatched event, so that the debugger will treat it as an uncaught - // error See ReactErrorUtils for more information. - // Before entering the begin phase, copy the work-in-progress onto a dummy - // fiber. If beginWork throws, we'll use this to reset the state. - var originalWorkInProgressCopy = assignFiberPropertiesInDEV( - dummyFiber, - unitOfWork - ); + function markFailedErrorBoundaryForHotReloading(fiber) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return; + } - try { - return beginWork$1(current, unitOfWork, lanes); - } catch (originalError) { - if ( - didSuspendOrErrorWhileHydratingDEV() || - originalError === SuspenseException || - originalError === SelectiveHydrationException || - (originalError !== null && - typeof originalError === "object" && - typeof originalError.then === "function") - ) { - // Don't replay promises. - // Don't replay errors if we are hydrating and have already suspended or handled an error - throw originalError; - } // Don't reset current debug fiber, since we're about to work on the - // same fiber again. - // Unwind the failed stack frame + if (typeof WeakSet !== "function") { + return; + } - resetSuspendedWorkLoopOnUnwind(unitOfWork); - unwindInterruptedWork(current, unitOfWork); // Restore the original properties of the fiber. + if (failedBoundaries === null) { + failedBoundaries = new WeakSet(); + } - assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); + failedBoundaries.add(fiber); + } + } + var scheduleRefresh = function (root, update) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return; + } - if (unitOfWork.mode & ProfileMode) { - // Reset the profiler timer. - startProfilerTimer(unitOfWork); - } // Run beginWork again. + var staleFamilies = update.staleFamilies, + updatedFamilies = update.updatedFamilies; + flushPassiveEffects(); + flushSync(function () { + scheduleFibersWithFamiliesRecursively( + root.current, + updatedFamilies, + staleFamilies + ); + }); + } + }; + var scheduleRoot = function (root, element) { + { + if (root.context !== emptyContextObject) { + // Super edge case: root has a legacy _renderSubtree context + // but we don't know the parentComponent so we can't pass it. + // Just ignore. We'll delete this with _renderSubtree code path later. + return; + } - invokeGuardedCallback( - null, - beginWork$1, - null, - current, - unitOfWork, - lanes - ); + flushPassiveEffects(); + flushSync(function () { + updateContainer(element, root, null, null); + }); + } + }; - if (hasCaughtError()) { - var replayError = clearCaughtError(); + function scheduleFibersWithFamiliesRecursively( + fiber, + updatedFamilies, + staleFamilies + ) { + { + var alternate = fiber.alternate, + child = fiber.child, + sibling = fiber.sibling, + tag = fiber.tag, + type = fiber.type; + var candidateType = null; + + switch (tag) { + case FunctionComponent: + case SimpleMemoComponent: + case ClassComponent: + candidateType = type; + break; - if ( - typeof replayError === "object" && - replayError !== null && - replayError._suppressLogging && - typeof originalError === "object" && - originalError !== null && - !originalError._suppressLogging - ) { - // If suppressed, let the flag carry over to the original error which is the one we'll rethrow. - originalError._suppressLogging = true; + case ForwardRef: + candidateType = type.render; + break; } - } // We always throw the original error in case the second render pass is not idempotent. - // This can happen if a memoized function or CommonJS module doesn't throw after first invocation. - - throw originalError; - } - }; -} else { - beginWork = beginWork$1; -} - -var didWarnAboutUpdateInRender = false; -var didWarnAboutUpdateInRenderForAnotherComponent; -{ - didWarnAboutUpdateInRenderForAnotherComponent = new Set(); -} + if (resolveFamily === null) { + throw new Error( + "Expected resolveFamily to be set during hot reload." + ); + } -function warnAboutRenderPhaseUpdatesInDEV(fiber) { - { - if (isRendering) { - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - var renderingComponentName = - (workInProgress && getComponentNameFromFiber(workInProgress)) || - "Unknown"; // Dedupe by the rendering component because it's the one that needs to be fixed. + var needsRender = false; + var needsRemount = false; - var dedupeKey = renderingComponentName; + if (candidateType !== null) { + var family = resolveFamily(candidateType); - if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) { - didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey); - var setStateComponentName = - getComponentNameFromFiber(fiber) || "Unknown"; + if (family !== undefined) { + if (staleFamilies.has(family)) { + needsRemount = true; + } else if (updatedFamilies.has(family)) { + if (tag === ClassComponent) { + needsRemount = true; + } else { + needsRender = true; + } + } + } + } - 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 - ); + if (failedBoundaries !== null) { + if ( + failedBoundaries.has(fiber) || // $FlowFixMe[incompatible-use] found when upgrading Flow + (alternate !== null && failedBoundaries.has(alternate)) + ) { + needsRemount = true; } + } - break; + if (needsRemount) { + fiber._debugNeedsRemount = true; } - case ClassComponent: { - if (!didWarnAboutUpdateInRender) { - error( - "Cannot update during an existing state transition (such as " + - "within `render`). Render methods should be a pure " + - "function of props and state." - ); + if (needsRemount || needsRender) { + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - didWarnAboutUpdateInRender = true; + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); } - - break; } - } - } - } -} - -function restorePendingUpdaters(root, lanes) { - { - if (isDevToolsPresent) { - var memoizedUpdaters = root.memoizedUpdaters; - memoizedUpdaters.forEach(function (schedulingFiber) { - addFiberToLanesMap(root, schedulingFiber, lanes); - }); // This function intentionally does not clear memoized updaters. - // Those may still be relevant to the current commit - // and a future one (e.g. Suspense). - } - } -} -var fakeActCallbackNode = {}; // $FlowFixMe[missing-local-annot] -function scheduleCallback(priorityLevel, callback) { - { - // If we're currently inside an `act` scope, bypass Scheduler and push to - // the `act` queue instead. - var actQueue = ReactCurrentActQueue.current; + if (child !== null && !needsRemount) { + scheduleFibersWithFamiliesRecursively( + child, + updatedFamilies, + staleFamilies + ); + } - if (actQueue !== null) { - actQueue.push(callback); - return fakeActCallbackNode; - } else { - return scheduleCallback$3(priorityLevel, callback); + if (sibling !== null) { + scheduleFibersWithFamiliesRecursively( + sibling, + updatedFamilies, + staleFamilies + ); + } + } } - } -} - -function shouldForceFlushFallbacksInDEV() { - // Never force flush in production. This function should get stripped out. - return ReactCurrentActQueue.current !== null; -} -function warnIfUpdatesNotWrappedWithActDEV(fiber) { - { - if (fiber.mode & ConcurrentMode) { - if (!isConcurrentActEnvironment()) { - // Not in an act environment. No need to warn. - return; - } - } else { - // Legacy mode has additional cases where we suppress a warning. - if (!isLegacyActEnvironment()) { - // Not in an act environment. No need to warn. - return; + var findHostInstancesForRefresh = function (root, families) { + { + var hostInstances = new Set(); + var types = new Set( + families.map(function (family) { + return family.current; + }) + ); + findHostInstancesForMatchingFibersRecursively( + root.current, + types, + hostInstances + ); + return hostInstances; } + }; - if (executionContext !== NoContext) { - // Legacy mode doesn't warn if the update is batched, i.e. - // batchedUpdates or flushSync. - return; - } + function findHostInstancesForMatchingFibersRecursively( + fiber, + types, + hostInstances + ) { + { + var child = fiber.child, + sibling = fiber.sibling, + tag = fiber.tag, + type = fiber.type; + var candidateType = null; + + switch (tag) { + case FunctionComponent: + case SimpleMemoComponent: + case ClassComponent: + candidateType = type; + break; - if ( - fiber.tag !== FunctionComponent && - fiber.tag !== ForwardRef && - fiber.tag !== SimpleMemoComponent - ) { - // For backwards compatibility with pre-hooks code, legacy mode only - // warns for updates that originate from a hook. - return; - } - } + case ForwardRef: + candidateType = type.render; + break; + } - if (ReactCurrentActQueue.current === null) { - var previousFiber = current; + var didMatch = false; - try { - setCurrentFiber(fiber); + if (candidateType !== null) { + if (types.has(candidateType)) { + didMatch = true; + } + } - 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) - ); - } finally { - if (previousFiber) { - setCurrentFiber(fiber); + if (didMatch) { + // We have a match. This only drills down to the closest host components. + // There's no need to search deeper because for the purpose of giving + // visual feedback, "flashing" outermost parent rectangles is sufficient. + findHostInstancesForFiberShallowly(fiber, hostInstances); } else { - resetCurrentFiber(); + // If there's no match, maybe there will be one further down in the child tree. + if (child !== null) { + findHostInstancesForMatchingFibersRecursively( + child, + types, + hostInstances + ); + } } - } - } - } -} -function warnIfSuspenseResolutionNotWrappedWithActDEV(root) { - { - if ( - root.tag !== LegacyRoot && - isConcurrentActEnvironment() && - ReactCurrentActQueue.current === null - ) { - 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" - ); + if (sibling !== null) { + findHostInstancesForMatchingFibersRecursively( + sibling, + types, + hostInstances + ); + } + } } - } -} -function setIsRunningInsertionEffect(isRunning) { - { - isRunningInsertionEffect = isRunning; - } -} + function findHostInstancesForFiberShallowly(fiber, hostInstances) { + { + var foundHostInstances = findChildHostInstancesForFiberShallowly( + fiber, + hostInstances + ); + + if (foundHostInstances) { + return; + } // If we didn't find any host children, fallback to closest host parent. -/* eslint-disable react-internal/prod-error-codes */ -// Used by React Refresh runtime through DevTools Global Hook. + var node = fiber; -var resolveFamily = null; -var failedBoundaries = null; -var setRefreshHandler = function (handler) { - { - resolveFamily = handler; - } -}; -function resolveFunctionForHotReloading(type) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return type; - } + while (true) { + switch (node.tag) { + case HostSingleton: + case HostComponent: + hostInstances.add(node.stateNode); + return; - var family = resolveFamily(type); + case HostPortal: + hostInstances.add(node.stateNode.containerInfo); + return; - if (family === undefined) { - return type; - } // Use the latest known implementation. + case HostRoot: + hostInstances.add(node.stateNode.containerInfo); + return; + } - return family.current; - } -} -function resolveClassForHotReloading(type) { - // No implementation differences. - return resolveFunctionForHotReloading(type); -} -function resolveForwardRefForHotReloading(type) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return type; + if (node.return === null) { + throw new Error("Expected to reach root first."); + } + + node = node.return; + } + } } - var family = resolveFamily(type); + function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { + { + var node = fiber; + var foundHostInstances = false; - if (family === undefined) { - // Check if we're dealing with a real forwardRef. Don't want to crash early. - if ( - type !== null && - type !== undefined && - typeof type.render === "function" - ) { - // ForwardRef is special because its resolved .type is an object, - // but it's possible that we only have its inner render function in the map. - // If that inner render function is different, we'll build a new forwardRef type. - var currentRender = resolveFunctionForHotReloading(type.render); - - if (type.render !== currentRender) { - var syntheticType = { - $$typeof: REACT_FORWARD_REF_TYPE, - render: currentRender - }; + while (true) { + if ( + node.tag === HostComponent || + node.tag === HostHoistable || + false + ) { + // We got a match. + foundHostInstances = true; + hostInstances.add(node.stateNode); // There may still be more, so keep searching. + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } + + if (node === fiber) { + return foundHostInstances; + } + + while (node.sibling === null) { + if (node.return === null || node.return === fiber) { + return foundHostInstances; + } - if (type.displayName !== undefined) { - syntheticType.displayName = type.displayName; + node = node.return; } - return syntheticType; + node.sibling.return = node.return; + node = node.sibling; } } - return type; - } // Use the latest known implementation. - - return family.current; - } -} -function isCompatibleFamilyForHotReloading(fiber, element) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. return false; } - var prevType = fiber.elementType; - var nextType = element.type; // If we got here, we know types aren't === equal. + var hasBadMapPolyfill; - var needsCompareFamilies = false; - var $$typeofNextType = - typeof nextType === "object" && nextType !== null - ? nextType.$$typeof - : null; + { + hasBadMapPolyfill = false; - switch (fiber.tag) { - case ClassComponent: { - if (typeof nextType === "function") { - needsCompareFamilies = true; - } + try { + var nonExtensibleObject = Object.preventExtensions({}); + /* eslint-disable no-new */ + + new Map([[nonExtensibleObject, null]]); + new Set([nonExtensibleObject]); + /* eslint-enable no-new */ + } catch (e) { + // TODO: Consider warning about bad polyfills + hasBadMapPolyfill = true; + } + } + + function FiberNode(tag, pendingProps, key, mode) { + // Instance + this.tag = tag; + this.key = key; + this.elementType = null; + this.type = null; + this.stateNode = null; // Fiber + + this.return = null; + this.child = null; + this.sibling = null; + this.index = 0; + this.ref = null; + this.refCleanup = null; + this.pendingProps = pendingProps; + this.memoizedProps = null; + this.updateQueue = null; + this.memoizedState = null; + this.dependencies = null; + this.mode = mode; // Effects + + this.flags = NoFlags$1; + this.subtreeFlags = NoFlags$1; + this.deletions = null; + this.lanes = NoLanes; + this.childLanes = NoLanes; + this.alternate = null; - break; + { + // Note: The following is done to avoid a v8 performance cliff. + // + // Initializing the fields below to smis and later updating them with + // double values will cause Fibers to end up having separate shapes. + // This behavior/bug has something to do with Object.preventExtension(). + // Fortunately this only impacts DEV builds. + // Unfortunately it makes React unusably slow for some applications. + // To work around this, initialize the fields below with doubles. + // + // Learn more about this here: + // https://github.com/facebook/react/issues/14365 + // https://bugs.chromium.org/p/v8/issues/detail?id=8538 + this.actualDuration = Number.NaN; + this.actualStartTime = Number.NaN; + this.selfBaseDuration = Number.NaN; + this.treeBaseDuration = Number.NaN; // It's okay to replace the initial doubles with smis after initialization. + // This won't trigger the performance cliff mentioned above, + // and it simplifies other profiler code (including DevTools). + + this.actualDuration = 0; + this.actualStartTime = -1; + this.selfBaseDuration = 0; + this.treeBaseDuration = 0; } - case FunctionComponent: { - if (typeof nextType === "function") { - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - // We don't know the inner type yet. - // We're going to assume that the lazy inner type is stable, - // and so it is sufficient to avoid reconciling it away. - // We're not going to unwrap or actually use the new lazy type. - needsCompareFamilies = true; - } + { + // This isn't directly used but is handy for debugging internals: + this._debugSource = null; + this._debugOwner = null; + this._debugNeedsRemount = false; + this._debugHookTypes = null; - break; - } + if ( + !hasBadMapPolyfill && + typeof Object.preventExtensions === "function" + ) { + Object.preventExtensions(this); + } + } + } // This is a constructor function, rather than a POJO constructor, still + // please ensure we do the following: + // 1) Nobody should add any instance methods on this. Instance methods can be + // more difficult to predict when they get optimized and they are almost + // never inlined properly in static compilers. + // 2) Nobody should rely on `instanceof Fiber` for type testing. We should + // always know when it is a fiber. + // 3) We might want to experiment with using numeric keys since they are easier + // to optimize in a non-JIT environment. + // 4) We can easily go from a constructor to a createFiber object literal if that + // is faster. + // 5) It should be easy to port this to a C struct and keep a C implementation + // compatible. + + function createFiber(tag, pendingProps, key, mode) { + // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors + return new FiberNode(tag, pendingProps, key, mode); + } + + function shouldConstruct(Component) { + var prototype = Component.prototype; + return !!(prototype && prototype.isReactComponent); + } + + function isSimpleFunctionComponent(type) { + return ( + typeof type === "function" && + !shouldConstruct(type) && + type.defaultProps === undefined + ); + } + function resolveLazyComponentTag(Component) { + if (typeof Component === "function") { + return shouldConstruct(Component) ? ClassComponent : FunctionComponent; + } else if (Component !== undefined && Component !== null) { + var $$typeof = Component.$$typeof; - case ForwardRef: { - if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - needsCompareFamilies = true; + if ($$typeof === REACT_FORWARD_REF_TYPE) { + return ForwardRef; } - break; + if ($$typeof === REACT_MEMO_TYPE) { + return MemoComponent; + } } - case MemoComponent: - case SimpleMemoComponent: { - if ($$typeofNextType === REACT_MEMO_TYPE) { - // TODO: if it was but can no longer be simple, - // we shouldn't set this. - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - needsCompareFamilies = true; + return IndeterminateComponent; + } // This is used to create an alternate fiber to do work on. + + function createWorkInProgress(current, pendingProps) { + var workInProgress = current.alternate; + + if (workInProgress === null) { + // We use a double buffering pooling technique because we know that we'll + // only ever need at most two versions of a tree. We pool the "other" unused + // node that we're free to reuse. This is lazily created to avoid allocating + // extra objects for things that are never updated. It also allow us to + // reclaim the extra memory if needed. + workInProgress = createFiber( + current.tag, + pendingProps, + current.key, + current.mode + ); + workInProgress.elementType = current.elementType; + workInProgress.type = current.type; + workInProgress.stateNode = current.stateNode; + + { + // DEV-only fields + workInProgress._debugSource = current._debugSource; + workInProgress._debugOwner = current._debugOwner; + workInProgress._debugHookTypes = current._debugHookTypes; } - break; - } + workInProgress.alternate = current; + current.alternate = workInProgress; + } else { + workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type. - default: - return false; - } // Check if both types have a family and it's the same one. + workInProgress.type = current.type; // We already have an alternate. + // Reset the effect tag. - if (needsCompareFamilies) { - // Note: memo() and forwardRef() we'll compare outer rather than inner type. - // This means both of them need to be registered to preserve state. - // If we unwrapped and compared the inner types for wrappers instead, - // then we would risk falsely saying two separate memo(Foo) - // calls are equivalent because they wrap the same Foo function. - var prevFamily = resolveFamily(prevType); // $FlowFixMe[not-a-function] found when upgrading Flow + workInProgress.flags = NoFlags$1; // The effects are no longer valid. - if (prevFamily !== undefined && prevFamily === resolveFamily(nextType)) { - return true; + workInProgress.subtreeFlags = NoFlags$1; + workInProgress.deletions = null; + + { + // We intentionally reset, rather than copy, actualDuration & actualStartTime. + // This prevents time from endlessly accumulating in new commits. + // This has the downside of resetting values for different priority renders, + // But works for yielding (the common case) and should support resuming. + workInProgress.actualDuration = 0; + workInProgress.actualStartTime = -1; + } + } // Reset all effects except static ones. + // Static effects are not specific to a render. + + workInProgress.flags = current.flags & StaticMask; + workInProgress.childLanes = current.childLanes; + workInProgress.lanes = current.lanes; + workInProgress.child = current.child; + workInProgress.memoizedProps = current.memoizedProps; + workInProgress.memoizedState = current.memoizedState; + workInProgress.updateQueue = current.updateQueue; // Clone the dependencies object. This is mutated during the render phase, so + // it cannot be shared with the current fiber. + + var currentDependencies = current.dependencies; + workInProgress.dependencies = + currentDependencies === null + ? null + : { + lanes: currentDependencies.lanes, + firstContext: currentDependencies.firstContext + }; // These will be overridden during the parent's reconciliation + + workInProgress.sibling = current.sibling; + workInProgress.index = current.index; + workInProgress.ref = current.ref; + workInProgress.refCleanup = current.refCleanup; + + { + workInProgress.selfBaseDuration = current.selfBaseDuration; + workInProgress.treeBaseDuration = current.treeBaseDuration; } - } - return false; - } -} -function markFailedErrorBoundaryForHotReloading(fiber) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return; - } + { + workInProgress._debugNeedsRemount = current._debugNeedsRemount; - if (typeof WeakSet !== "function") { - return; - } + switch (workInProgress.tag) { + case IndeterminateComponent: + case FunctionComponent: + case SimpleMemoComponent: + workInProgress.type = resolveFunctionForHotReloading(current.type); + break; - if (failedBoundaries === null) { - failedBoundaries = new WeakSet(); - } + case ClassComponent: + workInProgress.type = resolveClassForHotReloading(current.type); + break; - failedBoundaries.add(fiber); - } -} -var scheduleRefresh = function (root, update) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return; - } - - var staleFamilies = update.staleFamilies, - updatedFamilies = update.updatedFamilies; - flushPassiveEffects(); - flushSync(function () { - scheduleFibersWithFamiliesRecursively( - root.current, - updatedFamilies, - staleFamilies - ); - }); - } -}; -var scheduleRoot = function (root, element) { - { - if (root.context !== emptyContextObject) { - // Super edge case: root has a legacy _renderSubtree context - // but we don't know the parentComponent so we can't pass it. - // Just ignore. We'll delete this with _renderSubtree code path later. - return; - } - - flushPassiveEffects(); - flushSync(function () { - updateContainer(element, root, null, null); - }); - } -}; - -function scheduleFibersWithFamiliesRecursively( - fiber, - updatedFamilies, - staleFamilies -) { - { - var alternate = fiber.alternate, - child = fiber.child, - sibling = fiber.sibling, - tag = fiber.tag, - type = fiber.type; - var candidateType = null; - - switch (tag) { - case FunctionComponent: - case SimpleMemoComponent: - case ClassComponent: - candidateType = type; - break; - - case ForwardRef: - candidateType = type.render; - break; - } - - if (resolveFamily === null) { - throw new Error("Expected resolveFamily to be set during hot reload."); - } - - var needsRender = false; - var needsRemount = false; - - if (candidateType !== null) { - var family = resolveFamily(candidateType); - - if (family !== undefined) { - if (staleFamilies.has(family)) { - needsRemount = true; - } else if (updatedFamilies.has(family)) { - if (tag === ClassComponent) { - needsRemount = true; - } else { - needsRender = true; - } + case ForwardRef: + workInProgress.type = resolveForwardRefForHotReloading( + current.type + ); + break; } } - } - if (failedBoundaries !== null) { - if ( - failedBoundaries.has(fiber) || // $FlowFixMe[incompatible-use] found when upgrading Flow - (alternate !== null && failedBoundaries.has(alternate)) - ) { - needsRemount = true; - } - } + return workInProgress; + } // Used to reuse a Fiber for a second pass. - if (needsRemount) { - fiber._debugNeedsRemount = true; - } + function resetWorkInProgress(workInProgress, renderLanes) { + // This resets the Fiber to what createFiber or createWorkInProgress would + // have set the values to before during the first pass. Ideally this wouldn't + // be necessary but unfortunately many code paths reads from the workInProgress + // when they should be reading from current and writing to workInProgress. + // We assume pendingProps, index, key, ref, return are still untouched to + // avoid doing another reconciliation. + // Reset the effect flags but keep any Placement tags, since that's something + // that child fiber is setting, not the reconciliation. + workInProgress.flags &= StaticMask | Placement; // The effects are no longer valid. - if (needsRemount || needsRender) { - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + var current = workInProgress.alternate; - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } - } + if (current === null) { + // Reset to createFiber's initial values. + workInProgress.childLanes = NoLanes; + workInProgress.lanes = renderLanes; + workInProgress.child = null; + workInProgress.subtreeFlags = NoFlags$1; + workInProgress.memoizedProps = null; + workInProgress.memoizedState = null; + workInProgress.updateQueue = null; + workInProgress.dependencies = null; + workInProgress.stateNode = null; - if (child !== null && !needsRemount) { - scheduleFibersWithFamiliesRecursively( - child, - updatedFamilies, - staleFamilies - ); - } + { + // Note: We don't reset the actualTime counts. It's useful to accumulate + // actual time across multiple render passes. + workInProgress.selfBaseDuration = 0; + workInProgress.treeBaseDuration = 0; + } + } else { + // Reset to the cloned values that createWorkInProgress would've. + workInProgress.childLanes = current.childLanes; + workInProgress.lanes = current.lanes; + workInProgress.child = current.child; + workInProgress.subtreeFlags = NoFlags$1; + workInProgress.deletions = null; + workInProgress.memoizedProps = current.memoizedProps; + workInProgress.memoizedState = current.memoizedState; + workInProgress.updateQueue = current.updateQueue; // Needed because Blocks store data on type. - if (sibling !== null) { - scheduleFibersWithFamiliesRecursively( - sibling, - updatedFamilies, - staleFamilies - ); - } - } -} + workInProgress.type = current.type; // Clone the dependencies object. This is mutated during the render phase, so + // it cannot be shared with the current fiber. -var findHostInstancesForRefresh = function (root, families) { - { - var hostInstances = new Set(); - var types = new Set( - families.map(function (family) { - return family.current; - }) - ); - findHostInstancesForMatchingFibersRecursively( - root.current, - types, - hostInstances - ); - return hostInstances; - } -}; - -function findHostInstancesForMatchingFibersRecursively( - fiber, - types, - hostInstances -) { - { - var child = fiber.child, - sibling = fiber.sibling, - tag = fiber.tag, - type = fiber.type; - var candidateType = null; - - switch (tag) { - case FunctionComponent: - case SimpleMemoComponent: - case ClassComponent: - candidateType = type; - break; - - case ForwardRef: - candidateType = type.render; - break; - } - - var didMatch = false; - - if (candidateType !== null) { - if (types.has(candidateType)) { - didMatch = true; - } - } - - if (didMatch) { - // We have a match. This only drills down to the closest host components. - // There's no need to search deeper because for the purpose of giving - // visual feedback, "flashing" outermost parent rectangles is sufficient. - findHostInstancesForFiberShallowly(fiber, hostInstances); - } else { - // If there's no match, maybe there will be one further down in the child tree. - if (child !== null) { - findHostInstancesForMatchingFibersRecursively( - child, - types, - hostInstances - ); + var currentDependencies = current.dependencies; + workInProgress.dependencies = + currentDependencies === null + ? null + : { + lanes: currentDependencies.lanes, + firstContext: currentDependencies.firstContext + }; + + { + // Note: We don't reset the actualTime counts. It's useful to accumulate + // actual time across multiple render passes. + workInProgress.selfBaseDuration = current.selfBaseDuration; + workInProgress.treeBaseDuration = current.treeBaseDuration; + } } - } - if (sibling !== null) { - findHostInstancesForMatchingFibersRecursively( - sibling, - types, - hostInstances - ); + return workInProgress; } - } -} - -function findHostInstancesForFiberShallowly(fiber, hostInstances) { - { - var foundHostInstances = findChildHostInstancesForFiberShallowly( - fiber, - hostInstances - ); - - if (foundHostInstances) { - return; - } // If we didn't find any host children, fallback to closest host parent. - - var node = fiber; + function createHostRootFiber( + tag, + isStrictMode, + concurrentUpdatesByDefaultOverride + ) { + var mode; - while (true) { - switch (node.tag) { - case HostSingleton: - case HostComponent: - hostInstances.add(node.stateNode); - return; + if (tag === ConcurrentRoot) { + mode = ConcurrentMode; - case HostPortal: - hostInstances.add(node.stateNode.containerInfo); - return; + if (isStrictMode === true || createRootStrictEffectsByDefault) { + mode |= StrictLegacyMode | StrictEffectsMode; + } - case HostRoot: - hostInstances.add(node.stateNode.containerInfo); - return; + if ( + // Only for internal experiments. + concurrentUpdatesByDefaultOverride + ) { + mode |= ConcurrentUpdatesByDefaultMode; + } + } else { + mode = NoMode; } - if (node.return === null) { - throw new Error("Expected to reach root first."); + if (isDevToolsPresent) { + // Always collect profile timings when DevTools are present. + // This enables DevTools to start capturing timing at any point– + // Without some nodes in the tree having empty base times. + mode |= ProfileMode; } - node = node.return; + return createFiber(HostRoot, null, null, mode); } - } -} - -function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { - { - var node = fiber; - var foundHostInstances = false; + function createFiberFromTypeAndProps( + type, // React$ElementType + key, + pendingProps, + source, + owner, + mode, + lanes + ) { + var fiberTag = IndeterminateComponent; // The resolved type is set if we know what the final type will be. I.e. it's not lazy. - while (true) { - if (node.tag === HostComponent || node.tag === HostHoistable || false) { - // We got a match. - foundHostInstances = true; - hostInstances.add(node.stateNode); // There may still be more, so keep searching. - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; - } + var resolvedType = type; - if (node === fiber) { - return foundHostInstances; - } + if (typeof type === "function") { + if (shouldConstruct(type)) { + fiberTag = ClassComponent; - while (node.sibling === null) { - if (node.return === null || node.return === fiber) { - return foundHostInstances; + { + resolvedType = resolveClassForHotReloading(resolvedType); + } + } else { + { + resolvedType = resolveFunctionForHotReloading(resolvedType); + } } + } else if (typeof type === "string") { + { + fiberTag = HostComponent; + } + } else { + getTag: switch (type) { + case REACT_FRAGMENT_TYPE: + return createFiberFromFragment( + pendingProps.children, + mode, + lanes, + key + ); - node = node.return; - } + case REACT_STRICT_MODE_TYPE: + fiberTag = Mode; + mode |= StrictLegacyMode; - node.sibling.return = node.return; - node = node.sibling; - } - } + if ((mode & ConcurrentMode) !== NoMode) { + // Strict effects should never run on legacy roots + mode |= StrictEffectsMode; - return false; -} + if ( + enableDO_NOT_USE_disableStrictPassiveEffect && + pendingProps.DO_NOT_USE_disableStrictPassiveEffect + ) { + mode |= NoStrictPassiveEffectsMode; + } + } -var hasBadMapPolyfill; + break; -{ - hasBadMapPolyfill = false; + case REACT_PROFILER_TYPE: + return createFiberFromProfiler(pendingProps, mode, lanes, key); - try { - var nonExtensibleObject = Object.preventExtensions({}); - /* eslint-disable no-new */ + case REACT_SUSPENSE_TYPE: + return createFiberFromSuspense(pendingProps, mode, lanes, key); - new Map([[nonExtensibleObject, null]]); - new Set([nonExtensibleObject]); - /* eslint-enable no-new */ - } catch (e) { - // TODO: Consider warning about bad polyfills - hasBadMapPolyfill = true; - } -} + case REACT_SUSPENSE_LIST_TYPE: + return createFiberFromSuspenseList(pendingProps, mode, lanes, key); -function FiberNode(tag, pendingProps, key, mode) { - // Instance - this.tag = tag; - this.key = key; - this.elementType = null; - this.type = null; - this.stateNode = null; // Fiber - - this.return = null; - this.child = null; - this.sibling = null; - this.index = 0; - this.ref = null; - this.refCleanup = null; - this.pendingProps = pendingProps; - this.memoizedProps = null; - this.updateQueue = null; - this.memoizedState = null; - this.dependencies = null; - this.mode = mode; // Effects - - this.flags = NoFlags$1; - this.subtreeFlags = NoFlags$1; - this.deletions = null; - this.lanes = NoLanes; - this.childLanes = NoLanes; - this.alternate = null; - - { - // Note: The following is done to avoid a v8 performance cliff. - // - // Initializing the fields below to smis and later updating them with - // double values will cause Fibers to end up having separate shapes. - // This behavior/bug has something to do with Object.preventExtension(). - // Fortunately this only impacts DEV builds. - // Unfortunately it makes React unusably slow for some applications. - // To work around this, initialize the fields below with doubles. - // - // Learn more about this here: - // https://github.com/facebook/react/issues/14365 - // https://bugs.chromium.org/p/v8/issues/detail?id=8538 - this.actualDuration = Number.NaN; - this.actualStartTime = Number.NaN; - this.selfBaseDuration = Number.NaN; - this.treeBaseDuration = Number.NaN; // It's okay to replace the initial doubles with smis after initialization. - // This won't trigger the performance cliff mentioned above, - // and it simplifies other profiler code (including DevTools). - - this.actualDuration = 0; - this.actualStartTime = -1; - this.selfBaseDuration = 0; - this.treeBaseDuration = 0; - } - - { - // This isn't directly used but is handy for debugging internals: - this._debugSource = null; - this._debugOwner = null; - this._debugNeedsRemount = false; - this._debugHookTypes = null; - - if (!hasBadMapPolyfill && typeof Object.preventExtensions === "function") { - Object.preventExtensions(this); - } - } -} // This is a constructor function, rather than a POJO constructor, still -// please ensure we do the following: -// 1) Nobody should add any instance methods on this. Instance methods can be -// more difficult to predict when they get optimized and they are almost -// never inlined properly in static compilers. -// 2) Nobody should rely on `instanceof Fiber` for type testing. We should -// always know when it is a fiber. -// 3) We might want to experiment with using numeric keys since they are easier -// to optimize in a non-JIT environment. -// 4) We can easily go from a constructor to a createFiber object literal if that -// is faster. -// 5) It should be easy to port this to a C struct and keep a C implementation -// compatible. - -function createFiber(tag, pendingProps, key, mode) { - // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors - return new FiberNode(tag, pendingProps, key, mode); -} + case REACT_OFFSCREEN_TYPE: + return createFiberFromOffscreen(pendingProps, mode, lanes, key); -function shouldConstruct(Component) { - var prototype = Component.prototype; - return !!(prototype && prototype.isReactComponent); -} + case REACT_LEGACY_HIDDEN_TYPE: { + return createFiberFromLegacyHidden(pendingProps, mode, lanes, key); + } -function isSimpleFunctionComponent(type) { - return ( - typeof type === "function" && - !shouldConstruct(type) && - type.defaultProps === undefined - ); -} -function resolveLazyComponentTag(Component) { - if (typeof Component === "function") { - return shouldConstruct(Component) ? ClassComponent : FunctionComponent; - } else if (Component !== undefined && Component !== null) { - var $$typeof = Component.$$typeof; + // Fall through - if ($$typeof === REACT_FORWARD_REF_TYPE) { - return ForwardRef; - } + case REACT_SCOPE_TYPE: { + return createFiberFromScope(type, pendingProps, mode, lanes, key); + } - if ($$typeof === REACT_MEMO_TYPE) { - return MemoComponent; - } - } + // Fall through - return IndeterminateComponent; -} // This is used to create an alternate fiber to do work on. + case REACT_CACHE_TYPE: { + return createFiberFromCache(pendingProps, mode, lanes, key); + } -function createWorkInProgress(current, pendingProps) { - var workInProgress = current.alternate; + // Fall through - if (workInProgress === null) { - // We use a double buffering pooling technique because we know that we'll - // only ever need at most two versions of a tree. We pool the "other" unused - // node that we're free to reuse. This is lazily created to avoid allocating - // extra objects for things that are never updated. It also allow us to - // reclaim the extra memory if needed. - workInProgress = createFiber( - current.tag, - pendingProps, - current.key, - current.mode - ); - workInProgress.elementType = current.elementType; - workInProgress.type = current.type; - workInProgress.stateNode = current.stateNode; + case REACT_TRACING_MARKER_TYPE: + if (enableTransitionTracing) { + return createFiberFromTracingMarker( + pendingProps, + mode, + lanes, + key + ); + } - { - // DEV-only fields - workInProgress._debugSource = current._debugSource; - workInProgress._debugOwner = current._debugOwner; - workInProgress._debugHookTypes = current._debugHookTypes; - } + // Fall through - workInProgress.alternate = current; - current.alternate = workInProgress; - } else { - workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type. + case REACT_DEBUG_TRACING_MODE_TYPE: + if (enableDebugTracing) { + fiberTag = Mode; + mode |= DebugTracingMode; + break; + } - workInProgress.type = current.type; // We already have an alternate. - // Reset the effect tag. + // Fall through - workInProgress.flags = NoFlags$1; // The effects are no longer valid. + default: { + if (typeof type === "object" && type !== null) { + switch (type.$$typeof) { + case REACT_PROVIDER_TYPE: + fiberTag = ContextProvider; + break getTag; + + case REACT_CONTEXT_TYPE: + // This is a consumer + fiberTag = ContextConsumer; + break getTag; + + case REACT_FORWARD_REF_TYPE: + fiberTag = ForwardRef; + + { + resolvedType = + resolveForwardRefForHotReloading(resolvedType); + } - workInProgress.subtreeFlags = NoFlags$1; - workInProgress.deletions = null; + break getTag; - { - // We intentionally reset, rather than copy, actualDuration & actualStartTime. - // This prevents time from endlessly accumulating in new commits. - // This has the downside of resetting values for different priority renders, - // But works for yielding (the common case) and should support resuming. - workInProgress.actualDuration = 0; - workInProgress.actualStartTime = -1; - } - } // Reset all effects except static ones. - // Static effects are not specific to a render. - - workInProgress.flags = current.flags & StaticMask; - workInProgress.childLanes = current.childLanes; - workInProgress.lanes = current.lanes; - workInProgress.child = current.child; - workInProgress.memoizedProps = current.memoizedProps; - workInProgress.memoizedState = current.memoizedState; - workInProgress.updateQueue = current.updateQueue; // Clone the dependencies object. This is mutated during the render phase, so - // it cannot be shared with the current fiber. - - var currentDependencies = current.dependencies; - workInProgress.dependencies = - currentDependencies === null - ? null - : { - lanes: currentDependencies.lanes, - firstContext: currentDependencies.firstContext - }; // These will be overridden during the parent's reconciliation - - workInProgress.sibling = current.sibling; - workInProgress.index = current.index; - workInProgress.ref = current.ref; - workInProgress.refCleanup = current.refCleanup; - - { - workInProgress.selfBaseDuration = current.selfBaseDuration; - workInProgress.treeBaseDuration = current.treeBaseDuration; - } - - { - workInProgress._debugNeedsRemount = current._debugNeedsRemount; - - switch (workInProgress.tag) { - case IndeterminateComponent: - case FunctionComponent: - case SimpleMemoComponent: - workInProgress.type = resolveFunctionForHotReloading(current.type); - break; - - case ClassComponent: - workInProgress.type = resolveClassForHotReloading(current.type); - break; - - case ForwardRef: - workInProgress.type = resolveForwardRefForHotReloading(current.type); - break; - } - } - - return workInProgress; -} // Used to reuse a Fiber for a second pass. - -function resetWorkInProgress(workInProgress, renderLanes) { - // This resets the Fiber to what createFiber or createWorkInProgress would - // have set the values to before during the first pass. Ideally this wouldn't - // be necessary but unfortunately many code paths reads from the workInProgress - // when they should be reading from current and writing to workInProgress. - // We assume pendingProps, index, key, ref, return are still untouched to - // avoid doing another reconciliation. - // Reset the effect flags but keep any Placement tags, since that's something - // that child fiber is setting, not the reconciliation. - workInProgress.flags &= StaticMask | Placement; // The effects are no longer valid. - - var current = workInProgress.alternate; - - if (current === null) { - // Reset to createFiber's initial values. - workInProgress.childLanes = NoLanes; - workInProgress.lanes = renderLanes; - workInProgress.child = null; - workInProgress.subtreeFlags = NoFlags$1; - workInProgress.memoizedProps = null; - workInProgress.memoizedState = null; - workInProgress.updateQueue = null; - workInProgress.dependencies = null; - workInProgress.stateNode = null; + case REACT_MEMO_TYPE: + fiberTag = MemoComponent; + break getTag; - { - // Note: We don't reset the actualTime counts. It's useful to accumulate - // actual time across multiple render passes. - workInProgress.selfBaseDuration = 0; - workInProgress.treeBaseDuration = 0; - } - } else { - // Reset to the cloned values that createWorkInProgress would've. - workInProgress.childLanes = current.childLanes; - workInProgress.lanes = current.lanes; - workInProgress.child = current.child; - workInProgress.subtreeFlags = NoFlags$1; - workInProgress.deletions = null; - workInProgress.memoizedProps = current.memoizedProps; - workInProgress.memoizedState = current.memoizedState; - workInProgress.updateQueue = current.updateQueue; // Needed because Blocks store data on type. - - workInProgress.type = current.type; // Clone the dependencies object. This is mutated during the render phase, so - // it cannot be shared with the current fiber. - - var currentDependencies = current.dependencies; - workInProgress.dependencies = - currentDependencies === null - ? null - : { - lanes: currentDependencies.lanes, - firstContext: currentDependencies.firstContext - }; + case REACT_LAZY_TYPE: + fiberTag = LazyComponent; + resolvedType = null; + break getTag; + } + } - { - // Note: We don't reset the actualTime counts. It's useful to accumulate - // actual time across multiple render passes. - workInProgress.selfBaseDuration = current.selfBaseDuration; - workInProgress.treeBaseDuration = current.treeBaseDuration; - } - } + var info = ""; - return workInProgress; -} -function createHostRootFiber( - tag, - isStrictMode, - concurrentUpdatesByDefaultOverride -) { - var mode; + { + if ( + type === undefined || + (typeof type === "object" && + type !== null && + Object.keys(type).length === 0) + ) { + 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."; + } - if (tag === ConcurrentRoot) { - mode = ConcurrentMode; + var ownerName = owner ? getComponentNameFromFiber(owner) : null; - if (isStrictMode === true || createRootStrictEffectsByDefault) { - mode |= StrictLegacyMode | StrictEffectsMode; - } + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; + } + } - if ( - // Only for internal experiments. - concurrentUpdatesByDefaultOverride - ) { - mode |= ConcurrentUpdatesByDefaultMode; - } - } else { - mode = NoMode; - } + 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) + ); + } + } + } - if (isDevToolsPresent) { - // Always collect profile timings when DevTools are present. - // This enables DevTools to start capturing timing at any point– - // Without some nodes in the tree having empty base times. - mode |= ProfileMode; - } + var fiber = createFiber(fiberTag, pendingProps, key, mode); + fiber.elementType = type; + fiber.type = resolvedType; + fiber.lanes = lanes; - return createFiber(HostRoot, null, null, mode); -} -function createFiberFromTypeAndProps( - type, // React$ElementType - key, - pendingProps, - source, - owner, - mode, - lanes -) { - var fiberTag = IndeterminateComponent; // The resolved type is set if we know what the final type will be. I.e. it's not lazy. - - var resolvedType = type; - - if (typeof type === "function") { - if (shouldConstruct(type)) { - fiberTag = ClassComponent; + { + fiber._debugSource = source; + fiber._debugOwner = owner; + } + + return fiber; + } + function createFiberFromElement(element, mode, lanes) { + var source = null; + var owner = null; { - resolvedType = resolveClassForHotReloading(resolvedType); + source = element._source; + owner = element._owner; } - } else { + + var type = element.type; + var key = element.key; + var pendingProps = element.props; + var fiber = createFiberFromTypeAndProps( + type, + key, + pendingProps, + source, + owner, + mode, + lanes + ); + { - resolvedType = resolveFunctionForHotReloading(resolvedType); + fiber._debugSource = element._source; + fiber._debugOwner = element._owner; } + + return fiber; } - } else if (typeof type === "string") { - { - fiberTag = HostComponent; + function createFiberFromFragment(elements, mode, lanes, key) { + var fiber = createFiber(Fragment, elements, key, mode); + fiber.lanes = lanes; + return fiber; } - } else { - getTag: switch (type) { - case REACT_FRAGMENT_TYPE: - return createFiberFromFragment(pendingProps.children, mode, lanes, key); - - case REACT_STRICT_MODE_TYPE: - fiberTag = Mode; - mode |= StrictLegacyMode; - if ((mode & ConcurrentMode) !== NoMode) { - // Strict effects should never run on legacy roots - mode |= StrictEffectsMode; + function createFiberFromScope(scope, pendingProps, mode, lanes, key) { + var fiber = createFiber(ScopeComponent, pendingProps, key, mode); + fiber.type = scope; + fiber.elementType = scope; + fiber.lanes = lanes; + return fiber; + } - if ( - enableDO_NOT_USE_disableStrictPassiveEffect && - pendingProps.DO_NOT_USE_disableStrictPassiveEffect - ) { - mode |= NoStrictPassiveEffectsMode; - } + function createFiberFromProfiler(pendingProps, mode, lanes, key) { + { + if (typeof pendingProps.id !== "string") { + error( + 'Profiler must specify an "id" of type `string` as a prop. Received the type `%s` instead.', + typeof pendingProps.id + ); } + } + + var fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode); + fiber.elementType = REACT_PROFILER_TYPE; + fiber.lanes = lanes; + + { + fiber.stateNode = { + effectDuration: 0, + passiveEffectDuration: 0 + }; + } - break; + return fiber; + } + + function createFiberFromSuspense(pendingProps, mode, lanes, key) { + var fiber = createFiber(SuspenseComponent, pendingProps, key, mode); + fiber.elementType = REACT_SUSPENSE_TYPE; + fiber.lanes = lanes; + return fiber; + } + function createFiberFromSuspenseList(pendingProps, mode, lanes, key) { + var fiber = createFiber(SuspenseListComponent, pendingProps, key, mode); + fiber.elementType = REACT_SUSPENSE_LIST_TYPE; + fiber.lanes = lanes; + return fiber; + } + function createFiberFromOffscreen(pendingProps, mode, lanes, key) { + var fiber = createFiber(OffscreenComponent, pendingProps, key, mode); + fiber.elementType = REACT_OFFSCREEN_TYPE; + fiber.lanes = lanes; + var primaryChildInstance = { + _visibility: OffscreenVisible, + _pendingVisibility: OffscreenVisible, + _pendingMarkers: null, + _retryCache: null, + _transitions: null, + _current: null, + detach: function () { + return detachOffscreenInstance(primaryChildInstance); + }, + attach: function () { + return attachOffscreenInstance(primaryChildInstance); + } + }; + fiber.stateNode = primaryChildInstance; + return fiber; + } + function createFiberFromLegacyHidden(pendingProps, mode, lanes, key) { + var fiber = createFiber(LegacyHiddenComponent, pendingProps, key, mode); + fiber.elementType = REACT_LEGACY_HIDDEN_TYPE; + fiber.lanes = lanes; // Adding a stateNode for legacy hidden because it's currently using + // the offscreen implementation, which depends on a state node + + var instance = { + _visibility: OffscreenVisible, + _pendingVisibility: OffscreenVisible, + _pendingMarkers: null, + _transitions: null, + _retryCache: null, + _current: null, + detach: function () { + return detachOffscreenInstance(instance); + }, + attach: function () { + return attachOffscreenInstance(instance); + } + }; + fiber.stateNode = instance; + return fiber; + } + function createFiberFromCache(pendingProps, mode, lanes, key) { + var fiber = createFiber(CacheComponent, pendingProps, key, mode); + fiber.elementType = REACT_CACHE_TYPE; + fiber.lanes = lanes; + return fiber; + } + function createFiberFromTracingMarker(pendingProps, mode, lanes, key) { + var fiber = createFiber(TracingMarkerComponent, pendingProps, key, mode); + fiber.elementType = REACT_TRACING_MARKER_TYPE; + fiber.lanes = lanes; + var tracingMarkerInstance = { + tag: TransitionTracingMarker, + transitions: null, + pendingBoundaries: null, + aborts: null, + name: pendingProps.name + }; + fiber.stateNode = tracingMarkerInstance; + return fiber; + } + function createFiberFromText(content, mode, lanes) { + var fiber = createFiber(HostText, content, null, mode); + fiber.lanes = lanes; + return fiber; + } + function createFiberFromPortal(portal, mode, lanes) { + var pendingProps = portal.children !== null ? portal.children : []; + var fiber = createFiber(HostPortal, pendingProps, portal.key, mode); + fiber.lanes = lanes; + fiber.stateNode = { + containerInfo: portal.containerInfo, + pendingChildren: null, + // Used by persistent updates + implementation: portal.implementation + }; + return fiber; + } // Used for stashing WIP properties to replay failed work in DEV. + + function assignFiberPropertiesInDEV(target, source) { + if (target === null) { + // This Fiber's initial properties will always be overwritten. + // We only use a Fiber to ensure the same hidden class so DEV isn't slow. + target = createFiber(IndeterminateComponent, null, null, NoMode); + } // This is intentionally written as a list of all properties. + // We tried to use Object.assign() instead but this is called in + // the hottest path, and Object.assign() was too slow: + // https://github.com/facebook/react/issues/12502 + // This code is DEV-only so size is not a concern. + + target.tag = source.tag; + target.key = source.key; + target.elementType = source.elementType; + target.type = source.type; + target.stateNode = source.stateNode; + target.return = source.return; + target.child = source.child; + target.sibling = source.sibling; + target.index = source.index; + target.ref = source.ref; + target.refCleanup = source.refCleanup; + target.pendingProps = source.pendingProps; + target.memoizedProps = source.memoizedProps; + target.updateQueue = source.updateQueue; + target.memoizedState = source.memoizedState; + target.dependencies = source.dependencies; + target.mode = source.mode; + target.flags = source.flags; + target.subtreeFlags = source.subtreeFlags; + target.deletions = source.deletions; + target.lanes = source.lanes; + target.childLanes = source.childLanes; + target.alternate = source.alternate; - case REACT_PROFILER_TYPE: - return createFiberFromProfiler(pendingProps, mode, lanes, key); + { + target.actualDuration = source.actualDuration; + target.actualStartTime = source.actualStartTime; + target.selfBaseDuration = source.selfBaseDuration; + target.treeBaseDuration = source.treeBaseDuration; + } - case REACT_SUSPENSE_TYPE: - return createFiberFromSuspense(pendingProps, mode, lanes, key); + target._debugSource = source._debugSource; + target._debugOwner = source._debugOwner; + target._debugNeedsRemount = source._debugNeedsRemount; + target._debugHookTypes = source._debugHookTypes; + return target; + } - case REACT_SUSPENSE_LIST_TYPE: - return createFiberFromSuspenseList(pendingProps, mode, lanes, key); + function FiberRootNode( + containerInfo, // $FlowFixMe[missing-local-annot] + tag, + hydrate, + identifierPrefix, + onRecoverableError, + formState + ) { + this.tag = tag; + this.containerInfo = containerInfo; + this.pendingChildren = null; + this.current = null; + this.pingCache = null; + this.finishedWork = null; + this.timeoutHandle = noTimeout; + this.cancelPendingCommit = null; + this.context = null; + this.pendingContext = null; + this.next = null; + this.callbackNode = null; + this.callbackPriority = NoLane; + this.expirationTimes = createLaneMap(NoTimestamp); + this.pendingLanes = NoLanes; + this.suspendedLanes = NoLanes; + this.pingedLanes = NoLanes; + this.expiredLanes = NoLanes; + this.finishedLanes = NoLanes; + this.errorRecoveryDisabledLanes = NoLanes; + this.shellSuspendCounter = 0; + this.entangledLanes = NoLanes; + this.entanglements = createLaneMap(NoLanes); + this.hiddenUpdates = createLaneMap(null); + this.identifierPrefix = identifierPrefix; + this.onRecoverableError = onRecoverableError; - case REACT_OFFSCREEN_TYPE: - return createFiberFromOffscreen(pendingProps, mode, lanes, key); + { + this.pooledCache = null; + this.pooledCacheLanes = NoLanes; + } - case REACT_LEGACY_HIDDEN_TYPE: { - return createFiberFromLegacyHidden(pendingProps, mode, lanes, key); + { + this.hydrationCallbacks = null; } - // Fall through + this.formState = formState; + this.incompleteTransitions = new Map(); - case REACT_SCOPE_TYPE: { - return createFiberFromScope(type, pendingProps, mode, lanes, key); - } + if (enableTransitionTracing) { + this.transitionCallbacks = null; + var transitionLanesMap = (this.transitionLanes = []); - // Fall through + for (var i = 0; i < TotalLanes; i++) { + transitionLanesMap.push(null); + } + } - case REACT_CACHE_TYPE: { - return createFiberFromCache(pendingProps, mode, lanes, key); + { + this.effectDuration = 0; + this.passiveEffectDuration = 0; } - // Fall through + { + this.memoizedUpdaters = new Set(); + var pendingUpdatersLaneMap = (this.pendingUpdatersLaneMap = []); - case REACT_TRACING_MARKER_TYPE: - if (enableTransitionTracing) { - return createFiberFromTracingMarker(pendingProps, mode, lanes, key); + for (var _i = 0; _i < TotalLanes; _i++) { + pendingUpdatersLaneMap.push(new Set()); } + } - // Fall through + { + switch (tag) { + case ConcurrentRoot: + this._debugRootType = hydrate ? "hydrateRoot()" : "createRoot()"; + break; - case REACT_DEBUG_TRACING_MODE_TYPE: - if (enableDebugTracing) { - fiberTag = Mode; - mode |= DebugTracingMode; - break; + case LegacyRoot: + this._debugRootType = hydrate ? "hydrate()" : "render()"; + break; } + } + } - // Fall through + function createFiberRoot( + containerInfo, + tag, + hydrate, + initialChildren, + hydrationCallbacks, + isStrictMode, + concurrentUpdatesByDefaultOverride, // TODO: We have several of these arguments that are conceptually part of the + // host config, but because they are passed in at runtime, we have to thread + // them through the root constructor. Perhaps we should put them all into a + // single type, like a DynamicHostConfig that is defined by the renderer. + identifierPrefix, + onRecoverableError, + transitionCallbacks, + formState + ) { + // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + var root = new FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError, + formState + ); - default: { - if (typeof type === "object" && type !== null) { - switch (type.$$typeof) { - case REACT_PROVIDER_TYPE: - fiberTag = ContextProvider; - break getTag; + { + root.hydrationCallbacks = hydrationCallbacks; + } - case REACT_CONTEXT_TYPE: - // This is a consumer - fiberTag = ContextConsumer; - break getTag; + if (enableTransitionTracing) { + root.transitionCallbacks = transitionCallbacks; + } // Cyclic construction. This cheats the type system right now because + // stateNode is any. + + var uninitializedFiber = createHostRootFiber( + tag, + isStrictMode, + concurrentUpdatesByDefaultOverride + ); + root.current = uninitializedFiber; + uninitializedFiber.stateNode = root; - case REACT_FORWARD_REF_TYPE: - fiberTag = ForwardRef; + { + var initialCache = createCache(); + retainCache(initialCache); // The pooledCache is a fresh cache instance that is used temporarily + // for newly mounted boundaries during a render. In general, the + // pooledCache is always cleared from the root at the end of a render: + // it is either released when render commits, or moved to an Offscreen + // component if rendering suspends. Because the lifetime of the pooled + // cache is distinct from the main memoizedState.cache, it must be + // retained separately. + + root.pooledCache = initialCache; + retainCache(initialCache); + var initialState = { + element: initialChildren, + isDehydrated: hydrate, + cache: initialCache + }; + uninitializedFiber.memoizedState = initialState; + } - { - resolvedType = resolveForwardRefForHotReloading(resolvedType); - } + initializeUpdateQueue(uninitializedFiber); + return root; + } - break getTag; + // Might add PROFILE later. - case REACT_MEMO_TYPE: - fiberTag = MemoComponent; - break getTag; + var didWarnAboutNestedUpdates; - case REACT_LAZY_TYPE: - fiberTag = LazyComponent; - resolvedType = null; - break getTag; - } - } + { + didWarnAboutNestedUpdates = false; + } - var info = ""; + function getContextForSubtree(parentComponent) { + if (!parentComponent) { + return emptyContextObject; + } - { - if ( - type === undefined || - (typeof type === "object" && - type !== null && - Object.keys(type).length === 0) - ) { - 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."; - } + var fiber = get(parentComponent); + var parentContext = findCurrentUnmaskedContext(); - var ownerName = owner ? getComponentNameFromFiber(owner) : null; + if (fiber.tag === ClassComponent) { + var Component = fiber.type; - if (ownerName) { - info += "\n\nCheck the render method of `" + ownerName + "`."; - } + if (isContextProvider()) { + return processChildContext(fiber, Component, parentContext); } - - 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) - ); } - } - } - var fiber = createFiber(fiberTag, pendingProps, key, mode); - fiber.elementType = type; - fiber.type = resolvedType; - fiber.lanes = lanes; - - { - fiber._debugSource = source; - fiber._debugOwner = owner; - } - - return fiber; -} -function createFiberFromElement(element, mode, lanes) { - var source = null; - var owner = null; - - { - source = element._source; - owner = element._owner; - } - - var type = element.type; - var key = element.key; - var pendingProps = element.props; - var fiber = createFiberFromTypeAndProps( - type, - key, - pendingProps, - source, - owner, - mode, - lanes - ); - - { - fiber._debugSource = element._source; - fiber._debugOwner = element._owner; - } - - return fiber; -} -function createFiberFromFragment(elements, mode, lanes, key) { - var fiber = createFiber(Fragment, elements, key, mode); - fiber.lanes = lanes; - return fiber; -} - -function createFiberFromScope(scope, pendingProps, mode, lanes, key) { - var fiber = createFiber(ScopeComponent, pendingProps, key, mode); - fiber.type = scope; - fiber.elementType = scope; - fiber.lanes = lanes; - return fiber; -} + return parentContext; + } -function createFiberFromProfiler(pendingProps, mode, lanes, key) { - { - if (typeof pendingProps.id !== "string") { - error( - 'Profiler must specify an "id" of type `string` as a prop. Received the type `%s` instead.', - typeof pendingProps.id + function createContainer( + containerInfo, + tag, + hydrationCallbacks, + isStrictMode, + concurrentUpdatesByDefaultOverride, + identifierPrefix, + onRecoverableError, + transitionCallbacks + ) { + var hydrate = false; + var initialChildren = null; + return createFiberRoot( + containerInfo, + tag, + hydrate, + initialChildren, + hydrationCallbacks, + isStrictMode, + concurrentUpdatesByDefaultOverride, + identifierPrefix, + onRecoverableError, + transitionCallbacks, + null ); } - } - - var fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode); - fiber.elementType = REACT_PROFILER_TYPE; - fiber.lanes = lanes; + function updateContainer(element, container, parentComponent, callback) { + { + onScheduleRoot(container, element); + } - { - fiber.stateNode = { - effectDuration: 0, - passiveEffectDuration: 0 - }; - } + var current$1 = container.current; + var lane = requestUpdateLane(current$1); - return fiber; -} + if (enableSchedulingProfiler) { + markRenderScheduled(lane); + } -function createFiberFromSuspense(pendingProps, mode, lanes, key) { - var fiber = createFiber(SuspenseComponent, pendingProps, key, mode); - fiber.elementType = REACT_SUSPENSE_TYPE; - fiber.lanes = lanes; - return fiber; -} -function createFiberFromSuspenseList(pendingProps, mode, lanes, key) { - var fiber = createFiber(SuspenseListComponent, pendingProps, key, mode); - fiber.elementType = REACT_SUSPENSE_LIST_TYPE; - fiber.lanes = lanes; - return fiber; -} -function createFiberFromOffscreen(pendingProps, mode, lanes, key) { - var fiber = createFiber(OffscreenComponent, pendingProps, key, mode); - fiber.elementType = REACT_OFFSCREEN_TYPE; - fiber.lanes = lanes; - var primaryChildInstance = { - _visibility: OffscreenVisible, - _pendingVisibility: OffscreenVisible, - _pendingMarkers: null, - _retryCache: null, - _transitions: null, - _current: null, - detach: function () { - return detachOffscreenInstance(primaryChildInstance); - }, - attach: function () { - return attachOffscreenInstance(primaryChildInstance); - } - }; - fiber.stateNode = primaryChildInstance; - return fiber; -} -function createFiberFromLegacyHidden(pendingProps, mode, lanes, key) { - var fiber = createFiber(LegacyHiddenComponent, pendingProps, key, mode); - fiber.elementType = REACT_LEGACY_HIDDEN_TYPE; - fiber.lanes = lanes; // Adding a stateNode for legacy hidden because it's currently using - // the offscreen implementation, which depends on a state node - - var instance = { - _visibility: OffscreenVisible, - _pendingVisibility: OffscreenVisible, - _pendingMarkers: null, - _transitions: null, - _retryCache: null, - _current: null, - detach: function () { - return detachOffscreenInstance(instance); - }, - attach: function () { - return attachOffscreenInstance(instance); - } - }; - fiber.stateNode = instance; - return fiber; -} -function createFiberFromCache(pendingProps, mode, lanes, key) { - var fiber = createFiber(CacheComponent, pendingProps, key, mode); - fiber.elementType = REACT_CACHE_TYPE; - fiber.lanes = lanes; - return fiber; -} -function createFiberFromTracingMarker(pendingProps, mode, lanes, key) { - var fiber = createFiber(TracingMarkerComponent, pendingProps, key, mode); - fiber.elementType = REACT_TRACING_MARKER_TYPE; - fiber.lanes = lanes; - var tracingMarkerInstance = { - tag: TransitionTracingMarker, - transitions: null, - pendingBoundaries: null, - aborts: null, - name: pendingProps.name - }; - fiber.stateNode = tracingMarkerInstance; - return fiber; -} -function createFiberFromText(content, mode, lanes) { - var fiber = createFiber(HostText, content, null, mode); - fiber.lanes = lanes; - return fiber; -} -function createFiberFromPortal(portal, mode, lanes) { - var pendingProps = portal.children !== null ? portal.children : []; - var fiber = createFiber(HostPortal, pendingProps, portal.key, mode); - fiber.lanes = lanes; - fiber.stateNode = { - containerInfo: portal.containerInfo, - pendingChildren: null, - // Used by persistent updates - implementation: portal.implementation - }; - return fiber; -} // Used for stashing WIP properties to replay failed work in DEV. - -function assignFiberPropertiesInDEV(target, source) { - if (target === null) { - // This Fiber's initial properties will always be overwritten. - // We only use a Fiber to ensure the same hidden class so DEV isn't slow. - target = createFiber(IndeterminateComponent, null, null, NoMode); - } // This is intentionally written as a list of all properties. - // We tried to use Object.assign() instead but this is called in - // the hottest path, and Object.assign() was too slow: - // https://github.com/facebook/react/issues/12502 - // This code is DEV-only so size is not a concern. - - target.tag = source.tag; - target.key = source.key; - target.elementType = source.elementType; - target.type = source.type; - target.stateNode = source.stateNode; - target.return = source.return; - target.child = source.child; - target.sibling = source.sibling; - target.index = source.index; - target.ref = source.ref; - target.refCleanup = source.refCleanup; - target.pendingProps = source.pendingProps; - target.memoizedProps = source.memoizedProps; - target.updateQueue = source.updateQueue; - target.memoizedState = source.memoizedState; - target.dependencies = source.dependencies; - target.mode = source.mode; - target.flags = source.flags; - target.subtreeFlags = source.subtreeFlags; - target.deletions = source.deletions; - target.lanes = source.lanes; - target.childLanes = source.childLanes; - target.alternate = source.alternate; - - { - target.actualDuration = source.actualDuration; - target.actualStartTime = source.actualStartTime; - target.selfBaseDuration = source.selfBaseDuration; - target.treeBaseDuration = source.treeBaseDuration; - } - - target._debugSource = source._debugSource; - target._debugOwner = source._debugOwner; - target._debugNeedsRemount = source._debugNeedsRemount; - target._debugHookTypes = source._debugHookTypes; - return target; -} + var context = getContextForSubtree(parentComponent); -function FiberRootNode( - containerInfo, // $FlowFixMe[missing-local-annot] - tag, - hydrate, - identifierPrefix, - onRecoverableError, - formState -) { - this.tag = tag; - this.containerInfo = containerInfo; - this.pendingChildren = null; - this.current = null; - this.pingCache = null; - this.finishedWork = null; - this.timeoutHandle = noTimeout; - this.cancelPendingCommit = null; - this.context = null; - this.pendingContext = null; - this.next = null; - this.callbackNode = null; - this.callbackPriority = NoLane; - this.expirationTimes = createLaneMap(NoTimestamp); - this.pendingLanes = NoLanes; - this.suspendedLanes = NoLanes; - this.pingedLanes = NoLanes; - this.expiredLanes = NoLanes; - this.finishedLanes = NoLanes; - this.errorRecoveryDisabledLanes = NoLanes; - this.shellSuspendCounter = 0; - this.entangledLanes = NoLanes; - this.entanglements = createLaneMap(NoLanes); - this.hiddenUpdates = createLaneMap(null); - this.identifierPrefix = identifierPrefix; - this.onRecoverableError = onRecoverableError; - - { - this.pooledCache = null; - this.pooledCacheLanes = NoLanes; - } - - { - this.hydrationCallbacks = null; - } - - this.formState = formState; - this.incompleteTransitions = new Map(); - - if (enableTransitionTracing) { - this.transitionCallbacks = null; - var transitionLanesMap = (this.transitionLanes = []); - - for (var i = 0; i < TotalLanes; i++) { - transitionLanesMap.push(null); - } - } - - { - this.effectDuration = 0; - this.passiveEffectDuration = 0; - } - - { - this.memoizedUpdaters = new Set(); - var pendingUpdatersLaneMap = (this.pendingUpdatersLaneMap = []); - - for (var _i = 0; _i < TotalLanes; _i++) { - pendingUpdatersLaneMap.push(new Set()); - } - } - - { - switch (tag) { - case ConcurrentRoot: - this._debugRootType = hydrate ? "hydrateRoot()" : "createRoot()"; - break; - - case LegacyRoot: - this._debugRootType = hydrate ? "hydrate()" : "render()"; - break; - } - } -} + if (container.context === null) { + container.context = context; + } else { + container.pendingContext = context; + } -function createFiberRoot( - containerInfo, - tag, - hydrate, - initialChildren, - hydrationCallbacks, - isStrictMode, - concurrentUpdatesByDefaultOverride, // TODO: We have several of these arguments that are conceptually part of the - // host config, but because they are passed in at runtime, we have to thread - // them through the root constructor. Perhaps we should put them all into a - // single type, like a DynamicHostConfig that is defined by the renderer. - identifierPrefix, - onRecoverableError, - transitionCallbacks, - formState -) { - // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions - var root = new FiberRootNode( - containerInfo, - tag, - hydrate, - identifierPrefix, - onRecoverableError, - formState - ); - - { - root.hydrationCallbacks = hydrationCallbacks; - } - - if (enableTransitionTracing) { - root.transitionCallbacks = transitionCallbacks; - } // Cyclic construction. This cheats the type system right now because - // stateNode is any. - - var uninitializedFiber = createHostRootFiber( - tag, - isStrictMode, - concurrentUpdatesByDefaultOverride - ); - root.current = uninitializedFiber; - uninitializedFiber.stateNode = root; - - { - var initialCache = createCache(); - retainCache(initialCache); // The pooledCache is a fresh cache instance that is used temporarily - // for newly mounted boundaries during a render. In general, the - // pooledCache is always cleared from the root at the end of a render: - // it is either released when render commits, or moved to an Offscreen - // component if rendering suspends. Because the lifetime of the pooled - // cache is distinct from the main memoizedState.cache, it must be - // retained separately. - - root.pooledCache = initialCache; - retainCache(initialCache); - var initialState = { - element: initialChildren, - isDehydrated: hydrate, - cache: initialCache - }; - uninitializedFiber.memoizedState = initialState; - } + { + if (isRendering && current !== null && !didWarnAboutNestedUpdates) { + didWarnAboutNestedUpdates = true; - initializeUpdateQueue(uninitializedFiber); - return root; -} + 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" + ); + } + } -// Might add PROFILE later. + var update = createUpdate(lane); // Caution: React DevTools currently depends on this property + // being called "element". -var didWarnAboutNestedUpdates; + update.payload = { + element: element + }; + callback = callback === undefined ? null : callback; -{ - didWarnAboutNestedUpdates = false; -} + if (callback !== null) { + { + if (typeof callback !== "function") { + error( + "render(...): Expected the last optional `callback` argument to be a " + + "function. Instead received: %s.", + callback + ); + } + } -function getContextForSubtree(parentComponent) { - if (!parentComponent) { - return emptyContextObject; - } + update.callback = callback; + } - var fiber = get(parentComponent); - var parentContext = findCurrentUnmaskedContext(); + var root = enqueueUpdate(current$1, update, lane); - if (fiber.tag === ClassComponent) { - var Component = fiber.type; + if (root !== null) { + scheduleUpdateOnFiber(root, current$1, lane); + entangleTransitions(root, current$1, lane); + } - if (isContextProvider()) { - return processChildContext(fiber, Component, parentContext); + return lane; } - } - return parentContext; -} + var shouldErrorImpl = function (fiber) { + return null; + }; -function createContainer( - containerInfo, - tag, - hydrationCallbacks, - isStrictMode, - concurrentUpdatesByDefaultOverride, - identifierPrefix, - onRecoverableError, - transitionCallbacks -) { - var hydrate = false; - var initialChildren = null; - return createFiberRoot( - containerInfo, - tag, - hydrate, - initialChildren, - hydrationCallbacks, - isStrictMode, - concurrentUpdatesByDefaultOverride, - identifierPrefix, - onRecoverableError, - transitionCallbacks, - null - ); -} -function updateContainer(element, container, parentComponent, callback) { - { - onScheduleRoot(container, element); - } - - var current$1 = container.current; - var lane = requestUpdateLane(current$1); - - if (enableSchedulingProfiler) { - markRenderScheduled(lane); - } - - var context = getContextForSubtree(parentComponent); - - if (container.context === null) { - container.context = context; - } else { - container.pendingContext = context; - } - - { - if (isRendering && current !== null && !didWarnAboutNestedUpdates) { - didWarnAboutNestedUpdates = true; - - 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" - ); + function shouldError(fiber) { + return shouldErrorImpl(fiber); } - } - var update = createUpdate(lane); // Caution: React DevTools currently depends on this property - // being called "element". + var shouldSuspendImpl = function (fiber) { + return false; + }; - update.payload = { - element: element - }; - callback = callback === undefined ? null : callback; + function shouldSuspend(fiber) { + return shouldSuspendImpl(fiber); + } + var overrideHookState = null; + var overrideHookStateDeletePath = null; + var overrideHookStateRenamePath = null; + var overrideProps = null; + var overridePropsDeletePath = null; + var overridePropsRenamePath = null; + var scheduleUpdate = null; + var setErrorHandler = null; + var setSuspenseHandler = null; - if (callback !== null) { { - if (typeof callback !== "function") { - error( - "render(...): Expected the last optional `callback` argument to be a " + - "function. Instead received: %s.", - callback - ); - } - } + var copyWithDeleteImpl = function (obj, path, index) { + var key = path[index]; + var updated = isArray(obj) ? obj.slice() : assign({}, obj); - update.callback = callback; - } + if (index + 1 === path.length) { + if (isArray(updated)) { + updated.splice(key, 1); + } else { + delete updated[key]; + } - var root = enqueueUpdate(current$1, update, lane); + return updated; + } // $FlowFixMe[incompatible-use] number or string is fine here - if (root !== null) { - scheduleUpdateOnFiber(root, current$1, lane); - entangleTransitions(root, current$1, lane); - } + updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); + return updated; + }; - return lane; -} + var copyWithDelete = function (obj, path) { + return copyWithDeleteImpl(obj, path, 0); + }; -var shouldErrorImpl = function (fiber) { - return null; -}; + var copyWithRenameImpl = function (obj, oldPath, newPath, index) { + var oldKey = oldPath[index]; + var updated = isArray(obj) ? obj.slice() : assign({}, obj); -function shouldError(fiber) { - return shouldErrorImpl(fiber); -} + if (index + 1 === oldPath.length) { + var newKey = newPath[index]; // $FlowFixMe[incompatible-use] number or string is fine here -var shouldSuspendImpl = function (fiber) { - return false; -}; + updated[newKey] = updated[oldKey]; -function shouldSuspend(fiber) { - return shouldSuspendImpl(fiber); -} -var overrideHookState = null; -var overrideHookStateDeletePath = null; -var overrideHookStateRenamePath = null; -var overrideProps = null; -var overridePropsDeletePath = null; -var overridePropsRenamePath = null; -var scheduleUpdate = null; -var setErrorHandler = null; -var setSuspenseHandler = null; - -{ - var copyWithDeleteImpl = function (obj, path, index) { - var key = path[index]; - var updated = isArray(obj) ? obj.slice() : assign({}, obj); - - if (index + 1 === path.length) { - if (isArray(updated)) { - updated.splice(key, 1); - } else { - delete updated[key]; - } + if (isArray(updated)) { + updated.splice(oldKey, 1); + } else { + delete updated[oldKey]; + } + } else { + // $FlowFixMe[incompatible-use] number or string is fine here + updated[oldKey] = copyWithRenameImpl( + // $FlowFixMe[incompatible-use] number or string is fine here + obj[oldKey], + oldPath, + newPath, + index + 1 + ); + } - return updated; - } // $FlowFixMe[incompatible-use] number or string is fine here + return updated; + }; - updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); - return updated; - }; + var copyWithRename = function (obj, oldPath, newPath) { + if (oldPath.length !== newPath.length) { + warn("copyWithRename() expects paths of the same length"); - var copyWithDelete = function (obj, path) { - return copyWithDeleteImpl(obj, path, 0); - }; + return; + } else { + for (var i = 0; i < newPath.length - 1; i++) { + if (oldPath[i] !== newPath[i]) { + warn( + "copyWithRename() expects paths to be the same except for the deepest key" + ); - var copyWithRenameImpl = function (obj, oldPath, newPath, index) { - var oldKey = oldPath[index]; - var updated = isArray(obj) ? obj.slice() : assign({}, obj); + return; + } + } + } - if (index + 1 === oldPath.length) { - var newKey = newPath[index]; // $FlowFixMe[incompatible-use] number or string is fine here + return copyWithRenameImpl(obj, oldPath, newPath, 0); + }; - updated[newKey] = updated[oldKey]; + var copyWithSetImpl = function (obj, path, index, value) { + if (index >= path.length) { + return value; + } - if (isArray(updated)) { - updated.splice(oldKey, 1); - } else { - delete updated[oldKey]; - } - } else { - // $FlowFixMe[incompatible-use] number or string is fine here - updated[oldKey] = copyWithRenameImpl( - // $FlowFixMe[incompatible-use] number or string is fine here - obj[oldKey], - oldPath, - newPath, - index + 1 - ); - } + var key = path[index]; + var updated = isArray(obj) ? obj.slice() : assign({}, obj); // $FlowFixMe[incompatible-use] number or string is fine here - return updated; - }; + updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); + return updated; + }; - var copyWithRename = function (obj, oldPath, newPath) { - if (oldPath.length !== newPath.length) { - warn("copyWithRename() expects paths of the same length"); + var copyWithSet = function (obj, path, value) { + return copyWithSetImpl(obj, path, 0, value); + }; - return; - } else { - for (var i = 0; i < newPath.length - 1; i++) { - if (oldPath[i] !== newPath[i]) { - warn( - "copyWithRename() expects paths to be the same except for the deepest key" - ); + var findHook = function (fiber, id) { + // For now, the "id" of stateful hooks is just the stateful hook index. + // This may change in the future with e.g. nested hooks. + var currentHook = fiber.memoizedState; - return; + while (currentHook !== null && id > 0) { + currentHook = currentHook.next; + id--; } - } - } - return copyWithRenameImpl(obj, oldPath, newPath, 0); - }; + return currentHook; + }; // Support DevTools editable values for useState and useReducer. - var copyWithSetImpl = function (obj, path, index, value) { - if (index >= path.length) { - return value; - } + overrideHookState = function (fiber, id, path, value) { + var hook = findHook(fiber, id); - var key = path[index]; - var updated = isArray(obj) ? obj.slice() : assign({}, obj); // $FlowFixMe[incompatible-use] number or string is fine here + if (hook !== null) { + var newState = copyWithSet(hook.memoizedState, path, value); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, + // because there is no update we can add for useReducer hooks that won't trigger an error. + // (There's no appropriate action type for DevTools overrides.) + // As a result though, React will see the scheduled update as a noop and bailout. + // Shallow cloning props works as a workaround for now to bypass the bailout check. - updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); - return updated; - }; + fiber.memoizedProps = assign({}, fiber.memoizedProps); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - var copyWithSet = function (obj, path, value) { - return copyWithSetImpl(obj, path, 0, value); - }; - - var findHook = function (fiber, id) { - // For now, the "id" of stateful hooks is just the stateful hook index. - // This may change in the future with e.g. nested hooks. - var currentHook = fiber.memoizedState; + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + } + }; - while (currentHook !== null && id > 0) { - currentHook = currentHook.next; - id--; - } + overrideHookStateDeletePath = function (fiber, id, path) { + var hook = findHook(fiber, id); - return currentHook; - }; // Support DevTools editable values for useState and useReducer. + if (hook !== null) { + var newState = copyWithDelete(hook.memoizedState, path); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, + // because there is no update we can add for useReducer hooks that won't trigger an error. + // (There's no appropriate action type for DevTools overrides.) + // As a result though, React will see the scheduled update as a noop and bailout. + // Shallow cloning props works as a workaround for now to bypass the bailout check. - overrideHookState = function (fiber, id, path, value) { - var hook = findHook(fiber, id); + fiber.memoizedProps = assign({}, fiber.memoizedProps); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (hook !== null) { - var newState = copyWithSet(hook.memoizedState, path, value); - hook.memoizedState = newState; - hook.baseState = newState; // We aren't actually adding an update to the queue, - // because there is no update we can add for useReducer hooks that won't trigger an error. - // (There's no appropriate action type for DevTools overrides.) - // As a result though, React will see the scheduled update as a noop and bailout. - // Shallow cloning props works as a workaround for now to bypass the bailout check. + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + } + }; - fiber.memoizedProps = assign({}, fiber.memoizedProps); - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + overrideHookStateRenamePath = function (fiber, id, oldPath, newPath) { + var hook = findHook(fiber, id); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } - } - }; + if (hook !== null) { + var newState = copyWithRename(hook.memoizedState, oldPath, newPath); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, + // because there is no update we can add for useReducer hooks that won't trigger an error. + // (There's no appropriate action type for DevTools overrides.) + // As a result though, React will see the scheduled update as a noop and bailout. + // Shallow cloning props works as a workaround for now to bypass the bailout check. - overrideHookStateDeletePath = function (fiber, id, path) { - var hook = findHook(fiber, id); + fiber.memoizedProps = assign({}, fiber.memoizedProps); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (hook !== null) { - var newState = copyWithDelete(hook.memoizedState, path); - hook.memoizedState = newState; - hook.baseState = newState; // We aren't actually adding an update to the queue, - // because there is no update we can add for useReducer hooks that won't trigger an error. - // (There's no appropriate action type for DevTools overrides.) - // As a result though, React will see the scheduled update as a noop and bailout. - // Shallow cloning props works as a workaround for now to bypass the bailout check. + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + } + }; // Support DevTools props for function components, forwardRef, memo, host components, etc. - fiber.memoizedProps = assign({}, fiber.memoizedProps); - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + overrideProps = function (fiber, path, value) { + fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } - } - }; + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } - overrideHookStateRenamePath = function (fiber, id, oldPath, newPath) { - var hook = findHook(fiber, id); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (hook !== null) { - var newState = copyWithRename(hook.memoizedState, oldPath, newPath); - hook.memoizedState = newState; - hook.baseState = newState; // We aren't actually adding an update to the queue, - // because there is no update we can add for useReducer hooks that won't trigger an error. - // (There's no appropriate action type for DevTools overrides.) - // As a result though, React will see the scheduled update as a noop and bailout. - // Shallow cloning props works as a workaround for now to bypass the bailout check. + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + }; - fiber.memoizedProps = assign({}, fiber.memoizedProps); - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + overridePropsDeletePath = function (fiber, path) { + fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } - } - }; // Support DevTools props for function components, forwardRef, memo, host components, etc. + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } - overrideProps = function (fiber, path, value) { - fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (fiber.alternate) { - fiber.alternate.pendingProps = fiber.pendingProps; - } + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + }; - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + overridePropsRenamePath = function (fiber, oldPath, newPath) { + fiber.pendingProps = copyWithRename( + fiber.memoizedProps, + oldPath, + newPath + ); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } - }; + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } - overridePropsDeletePath = function (fiber, path) { - fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path); + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (fiber.alternate) { - fiber.alternate.pendingProps = fiber.pendingProps; - } + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + }; - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + scheduleUpdate = function (fiber) { + var root = enqueueConcurrentRenderForLane(fiber, SyncLane); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } - }; + if (root !== null) { + scheduleUpdateOnFiber(root, fiber, SyncLane); + } + }; - overridePropsRenamePath = function (fiber, oldPath, newPath) { - fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath); + setErrorHandler = function (newShouldErrorImpl) { + shouldErrorImpl = newShouldErrorImpl; + }; - if (fiber.alternate) { - fiber.alternate.pendingProps = fiber.pendingProps; + setSuspenseHandler = function (newShouldSuspendImpl) { + shouldSuspendImpl = newShouldSuspendImpl; + }; } - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + function findHostInstanceByFiber(fiber) { + var hostFiber = findCurrentHostFiber(fiber); - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); - } - }; - - scheduleUpdate = function (fiber) { - var root = enqueueConcurrentRenderForLane(fiber, SyncLane); + if (hostFiber === null) { + return null; + } - if (root !== null) { - scheduleUpdateOnFiber(root, fiber, SyncLane); + return hostFiber.stateNode; } - }; - setErrorHandler = function (newShouldErrorImpl) { - shouldErrorImpl = newShouldErrorImpl; - }; - - setSuspenseHandler = function (newShouldSuspendImpl) { - shouldSuspendImpl = newShouldSuspendImpl; - }; -} + function emptyFindFiberByHostInstance(instance) { + return null; + } -function findHostInstanceByFiber(fiber) { - var hostFiber = findCurrentHostFiber(fiber); + function getCurrentFiberForDevTools() { + return current; + } + + function injectIntoDevTools(devToolsConfig) { + var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance; + var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; + return injectInternals({ + bundleType: devToolsConfig.bundleType, + version: devToolsConfig.version, + rendererPackageName: devToolsConfig.rendererPackageName, + rendererConfig: devToolsConfig.rendererConfig, + overrideHookState: overrideHookState, + overrideHookStateDeletePath: overrideHookStateDeletePath, + overrideHookStateRenamePath: overrideHookStateRenamePath, + overrideProps: overrideProps, + overridePropsDeletePath: overridePropsDeletePath, + overridePropsRenamePath: overridePropsRenamePath, + setErrorHandler: setErrorHandler, + setSuspenseHandler: setSuspenseHandler, + scheduleUpdate: scheduleUpdate, + currentDispatcherRef: ReactCurrentDispatcher, + findHostInstanceByFiber: findHostInstanceByFiber, + findFiberByHostInstance: + findFiberByHostInstance || emptyFindFiberByHostInstance, + // React Refresh + findHostInstancesForRefresh: findHostInstancesForRefresh, + scheduleRefresh: scheduleRefresh, + scheduleRoot: scheduleRoot, + setRefreshHandler: setRefreshHandler, + // Enables DevTools to append owner stacks to error messages in DEV mode. + getCurrentFiber: getCurrentFiberForDevTools, + // Enables DevTools to detect reconciler version rather than renderer version + // which may not match for third party renderers. + reconcilerVersion: ReactVersion + }); + } - if (hostFiber === null) { - return null; - } + Mode$1.setCurrent( + // Change to 'art/modes/dom' for easier debugging via SVG + FastNoSideEffects + ); + /** Declarative fill-type objects; API design not finalized */ - return hostFiber.stateNode; -} + var slice = Array.prototype.slice; -function emptyFindFiberByHostInstance(instance) { - return null; -} + var LinearGradient = /*#__PURE__*/ (function () { + function LinearGradient(stops, x1, y1, x2, y2) { + this._args = slice.call(arguments); + } -function getCurrentFiberForDevTools() { - return current; -} + var _proto = LinearGradient.prototype; -function injectIntoDevTools(devToolsConfig) { - var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance; - var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; - return injectInternals({ - bundleType: devToolsConfig.bundleType, - version: devToolsConfig.version, - rendererPackageName: devToolsConfig.rendererPackageName, - rendererConfig: devToolsConfig.rendererConfig, - overrideHookState: overrideHookState, - overrideHookStateDeletePath: overrideHookStateDeletePath, - overrideHookStateRenamePath: overrideHookStateRenamePath, - overrideProps: overrideProps, - overridePropsDeletePath: overridePropsDeletePath, - overridePropsRenamePath: overridePropsRenamePath, - setErrorHandler: setErrorHandler, - setSuspenseHandler: setSuspenseHandler, - scheduleUpdate: scheduleUpdate, - currentDispatcherRef: ReactCurrentDispatcher, - findHostInstanceByFiber: findHostInstanceByFiber, - findFiberByHostInstance: - findFiberByHostInstance || emptyFindFiberByHostInstance, - // React Refresh - findHostInstancesForRefresh: findHostInstancesForRefresh, - scheduleRefresh: scheduleRefresh, - scheduleRoot: scheduleRoot, - setRefreshHandler: setRefreshHandler, - // Enables DevTools to append owner stacks to error messages in DEV mode. - getCurrentFiber: getCurrentFiberForDevTools, - // Enables DevTools to detect reconciler version rather than renderer version - // which may not match for third party renderers. - reconcilerVersion: ReactVersion - }); -} + _proto.applyFill = function applyFill(node) { + node.fillLinear.apply(node, this._args); + }; -Mode$1.setCurrent( - // Change to 'art/modes/dom' for easier debugging via SVG - FastNoSideEffects -); -/** Declarative fill-type objects; API design not finalized */ + return LinearGradient; + })(); -var slice = Array.prototype.slice; + var RadialGradient = /*#__PURE__*/ (function () { + function RadialGradient(stops, fx, fy, rx, ry, cx, cy) { + this._args = slice.call(arguments); + } -var LinearGradient = /*#__PURE__*/ (function () { - function LinearGradient(stops, x1, y1, x2, y2) { - this._args = slice.call(arguments); - } + var _proto2 = RadialGradient.prototype; - var _proto = LinearGradient.prototype; + _proto2.applyFill = function applyFill(node) { + node.fillRadial.apply(node, this._args); + }; - _proto.applyFill = function applyFill(node) { - node.fillLinear.apply(node, this._args); - }; + return RadialGradient; + })(); - return LinearGradient; -})(); + var Pattern = /*#__PURE__*/ (function () { + function Pattern(url, width, height, left, top) { + this._args = slice.call(arguments); + } -var RadialGradient = /*#__PURE__*/ (function () { - function RadialGradient(stops, fx, fy, rx, ry, cx, cy) { - this._args = slice.call(arguments); - } + var _proto3 = Pattern.prototype; - var _proto2 = RadialGradient.prototype; + _proto3.applyFill = function applyFill(node) { + node.fillImage.apply(node, this._args); + }; - _proto2.applyFill = function applyFill(node) { - node.fillRadial.apply(node, this._args); - }; + return Pattern; + })(); + /** React Components */ - return RadialGradient; -})(); + var Surface = /*#__PURE__*/ (function (_React$Component) { + _inheritsLoose(Surface, _React$Component); -var Pattern = /*#__PURE__*/ (function () { - function Pattern(url, width, height, left, top) { - this._args = slice.call(arguments); - } + function Surface() { + return _React$Component.apply(this, arguments) || this; + } - var _proto3 = Pattern.prototype; + var _proto4 = Surface.prototype; - _proto3.applyFill = function applyFill(node) { - node.fillImage.apply(node, this._args); - }; + _proto4.componentDidMount = function componentDidMount() { + var _this$props = this.props, + height = _this$props.height, + width = _this$props.width; + this._surface = Mode$1.Surface(+width, +height, this._tagRef); + this._mountNode = createContainer( + this._surface, + LegacyRoot, + null, + false, + false, + "" + ); + updateContainer(this.props.children, this._mountNode, this); + }; - return Pattern; -})(); -/** React Components */ + _proto4.componentDidUpdate = function componentDidUpdate( + prevProps, + prevState + ) { + var props = this.props; -var Surface = /*#__PURE__*/ (function (_React$Component) { - _inheritsLoose(Surface, _React$Component); + if ( + props.height !== prevProps.height || + props.width !== prevProps.width + ) { + this._surface.resize(+props.width, +props.height); + } - function Surface() { - return _React$Component.apply(this, arguments) || this; - } + updateContainer(this.props.children, this._mountNode, this); - var _proto4 = Surface.prototype; + if (this._surface.render) { + this._surface.render(); + } + }; - _proto4.componentDidMount = function componentDidMount() { - var _this$props = this.props, - height = _this$props.height, - width = _this$props.width; - this._surface = Mode$1.Surface(+width, +height, this._tagRef); - this._mountNode = createContainer( - this._surface, - LegacyRoot, - null, - false, - false, - "" - ); - updateContainer(this.props.children, this._mountNode, this); - }; + _proto4.componentWillUnmount = function componentWillUnmount() { + updateContainer(null, this._mountNode, this); + }; - _proto4.componentDidUpdate = function componentDidUpdate( - prevProps, - prevState - ) { - var props = this.props; + _proto4.render = function render() { + var _this = this; - if (props.height !== prevProps.height || props.width !== prevProps.width) { - this._surface.resize(+props.width, +props.height); - } + // This is going to be a placeholder because we don't know what it will + // actually resolve to because ART may render canvas, vml or svg tags here. + // We only allow a subset of properties since others might conflict with + // ART's properties. + var props = this.props; // TODO: ART's Canvas Mode overrides surface title and cursor - updateContainer(this.props.children, this._mountNode, this); + var Tag = Mode$1.Surface.tagName; + return /*#__PURE__*/ React.createElement(Tag, { + ref: function (ref) { + return (_this._tagRef = ref); + }, + accessKey: props.accessKey, + className: props.className, + draggable: props.draggable, + role: props.role, + style: props.style, + tabIndex: props.tabIndex, + title: props.title + }); + }; - if (this._surface.render) { - this._surface.render(); - } - }; + return Surface; + })(React.Component); - _proto4.componentWillUnmount = function componentWillUnmount() { - updateContainer(null, this._mountNode, this); - }; + var Text = /*#__PURE__*/ (function (_React$Component2) { + _inheritsLoose(Text, _React$Component2); - _proto4.render = function render() { - var _this = this; + function Text(props) { + var _this2; - // This is going to be a placeholder because we don't know what it will - // actually resolve to because ART may render canvas, vml or svg tags here. - // We only allow a subset of properties since others might conflict with - // ART's properties. - var props = this.props; // TODO: ART's Canvas Mode overrides surface title and cursor + _this2 = _React$Component2.call(this, props) || this; // We allow reading these props. Ideally we could expose the Text node as + // ref directly. - var Tag = Mode$1.Surface.tagName; - return /*#__PURE__*/ React.createElement(Tag, { - ref: function (ref) { - return (_this._tagRef = ref); - }, - accessKey: props.accessKey, - className: props.className, - draggable: props.draggable, - role: props.role, - style: props.style, - tabIndex: props.tabIndex, - title: props.title - }); - }; + ["height", "width", "x", "y"].forEach(function (key) { + Object.defineProperty(_assertThisInitialized(_this2), key, { + get: function () { + return this._text ? this._text[key] : undefined; + } + }); + }); + return _this2; + } - return Surface; -})(React.Component); + var _proto5 = Text.prototype; -var Text = /*#__PURE__*/ (function (_React$Component2) { - _inheritsLoose(Text, _React$Component2); + _proto5.render = function render() { + var _this3 = this; - function Text(props) { - var _this2; + // This means you can't have children that render into strings... + var T = TYPES.TEXT; + return /*#__PURE__*/ React.createElement( + T, + _extends({}, this.props, { + ref: function (t) { + return (_this3._text = t); + } + }), + childrenAsString(this.props.children) + ); + }; - _this2 = _React$Component2.call(this, props) || this; // We allow reading these props. Ideally we could expose the Text node as - // ref directly. + return Text; + })(React.Component); - ["height", "width", "x", "y"].forEach(function (key) { - Object.defineProperty(_assertThisInitialized(_this2), key, { - get: function () { - return this._text ? this._text[key] : undefined; - } - }); + injectIntoDevTools({ + findFiberByHostInstance: function () { + return null; + }, + bundleType: 1, + version: ReactVersion, + rendererPackageName: "react-art" }); - return _this2; - } - - var _proto5 = Text.prototype; - - _proto5.render = function render() { - var _this3 = this; - - // This means you can't have children that render into strings... - var T = TYPES.TEXT; - return /*#__PURE__*/ React.createElement( - T, - _extends({}, this.props, { - ref: function (t) { - return (_this3._text = t); - } - }), - childrenAsString(this.props.children) - ); - }; - - return Text; -})(React.Component); - -injectIntoDevTools({ - findFiberByHostInstance: function () { - return null; - }, - bundleType: 1, - version: ReactVersion, - rendererPackageName: "react-art" -}); -/** API */ - -var ClippingRectangle = TYPES.CLIPPING_RECTANGLE; -var Group = TYPES.GROUP; -var Shape = TYPES.SHAPE; -var Path = Mode$1.Path; - -exports.Transform = Transform; -exports.ClippingRectangle = ClippingRectangle; -exports.Group = Group; -exports.LinearGradient = LinearGradient; -exports.Path = Path; -exports.Pattern = Pattern; -exports.RadialGradient = RadialGradient; -exports.Shape = Shape; -exports.Surface = Surface; -exports.Text = Text; - - /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ -if ( - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop === - 'function' -) { - __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error()); -} - + /** API */ + + var ClippingRectangle = TYPES.CLIPPING_RECTANGLE; + var Group = TYPES.GROUP; + var Shape = TYPES.SHAPE; + var Path = Mode$1.Path; + + exports.Transform = Transform; + exports.ClippingRectangle = ClippingRectangle; + exports.Group = Group; + exports.LinearGradient = LinearGradient; + exports.Path = Path; + exports.Pattern = Pattern; + exports.RadialGradient = RadialGradient; + exports.Shape = Shape; + exports.Surface = Surface; + exports.Text = Text; + /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ + if ( + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined" && + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop === + "function" + ) { + __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error()); + } })(); } diff --git a/compiled/facebook-www/ReactART-prod.classic.js b/compiled/facebook-www/ReactART-prod.classic.js index 5de3d4a58ad45..1a0ff5a802a34 100644 --- a/compiled/facebook-www/ReactART-prod.classic.js +++ b/compiled/facebook-www/ReactART-prod.classic.js @@ -1,15 +1,15 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @noflow - * @nolint - * @preventMunge - * @preserve-invariant-messages - */ +/* + Copyright (c) Meta Platforms, Inc. and affiliates. + + This source code is licensed under the MIT license found in the + LICENSE file in the root directory of this source tree. + + @noflow + @nolint + @preventMunge + @preserve-invariant-messages +*/ "use strict"; var React = require("react"), Transform = require("art/core/transform"), @@ -10181,7 +10181,7 @@ var slice = Array.prototype.slice, return null; }, bundleType: 0, - version: "18.3.0-www-classic-daa48109", + version: "18.3.0-www-classic-e2c51dba", rendererPackageName: "react-art" }; var internals$jscomp$inline_1322 = { @@ -10212,7 +10212,7 @@ var internals$jscomp$inline_1322 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-www-classic-daa48109" + reconcilerVersion: "18.3.0-www-classic-e2c51dba" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_1323 = __REACT_DEVTOOLS_GLOBAL_HOOK__; diff --git a/compiled/facebook-www/ReactART-prod.modern.js b/compiled/facebook-www/ReactART-prod.modern.js index 4fa53a6125de9..5a41b3475b82b 100644 --- a/compiled/facebook-www/ReactART-prod.modern.js +++ b/compiled/facebook-www/ReactART-prod.modern.js @@ -1,15 +1,15 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @noflow - * @nolint - * @preventMunge - * @preserve-invariant-messages - */ +/* + Copyright (c) Meta Platforms, Inc. and affiliates. + + This source code is licensed under the MIT license found in the + LICENSE file in the root directory of this source tree. + + @noflow + @nolint + @preventMunge + @preserve-invariant-messages +*/ "use strict"; var React = require("react"), Transform = require("art/core/transform"), @@ -9850,7 +9850,7 @@ var slice = Array.prototype.slice, return null; }, bundleType: 0, - version: "18.3.0-www-modern-deff22e3", + version: "18.3.0-www-modern-e13466d9", rendererPackageName: "react-art" }; var internals$jscomp$inline_1302 = { @@ -9881,7 +9881,7 @@ var internals$jscomp$inline_1302 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-www-modern-deff22e3" + reconcilerVersion: "18.3.0-www-modern-e13466d9" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_1303 = __REACT_DEVTOOLS_GLOBAL_HOOK__; diff --git a/compiled/facebook-www/ReactDOM-dev.classic.js b/compiled/facebook-www/ReactDOM-dev.classic.js index f3369632a8c9d..4ea9df4303e68 100644 --- a/compiled/facebook-www/ReactDOM-dev.classic.js +++ b/compiled/facebook-www/ReactDOM-dev.classic.js @@ -1,4 +1,5 @@ /** + * @preserve * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the @@ -10,43265 +11,44052 @@ * @preserve-invariant-messages */ -'use strict'; +"use strict"; if (__DEV__) { - (function() { + (function () { + "use strict"; - 'use strict'; - -/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ -if ( - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart === - 'function' -) { - __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); -} - "use strict"; - -var Scheduler = require("scheduler"); -var React = require("react"); + /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ + if ( + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined" && + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart === + "function" + ) { + __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); + } + var Scheduler = require("scheduler"); + var React = require("react"); -var assign = Object.assign; + var assign = Object.assign; -// This refers to a WWW module. -var warningWWW = require("warning"); + // This refers to a WWW module. + var warningWWW = require("warning"); -var suppressWarning = false; -function setSuppressWarning(newSuppressWarning) { - { - suppressWarning = newSuppressWarning; - } -} -function warn(format) { - { - if (!suppressWarning) { - for ( - var _len = arguments.length, - args = new Array(_len > 1 ? _len - 1 : 0), - _key = 1; - _key < _len; - _key++ - ) { - args[_key - 1] = arguments[_key]; + var suppressWarning = false; + function setSuppressWarning(newSuppressWarning) { + { + suppressWarning = newSuppressWarning; } + } + function warn(format) { + { + if (!suppressWarning) { + for ( + var _len = arguments.length, + args = new Array(_len > 1 ? _len - 1 : 0), + _key = 1; + _key < _len; + _key++ + ) { + args[_key - 1] = arguments[_key]; + } - printWarning("warn", format, args); + printWarning("warn", format, args); + } + } } - } -} -function error(format) { - { - if (!suppressWarning) { - for ( - var _len2 = arguments.length, - args = new Array(_len2 > 1 ? _len2 - 1 : 0), - _key2 = 1; - _key2 < _len2; - _key2++ - ) { - args[_key2 - 1] = arguments[_key2]; + function error(format) { + { + if (!suppressWarning) { + for ( + var _len2 = arguments.length, + args = new Array(_len2 > 1 ? _len2 - 1 : 0), + _key2 = 1; + _key2 < _len2; + _key2++ + ) { + args[_key2 - 1] = arguments[_key2]; + } + + printWarning("error", format, args); + } } + } + + function printWarning(level, format, args) { + { + var React = require("react"); + + var ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. - printWarning("error", format, args); + if (ReactSharedInternals != null) { + var ReactDebugCurrentFrame = + ReactSharedInternals.ReactDebugCurrentFrame; + var stack = ReactDebugCurrentFrame.getStackAddendum(); + + if (stack !== "") { + format += "%s"; + args.push(stack); + } + } // TODO: don't ignore level and pass it down somewhere too. + + args.unshift(format); + args.unshift(false); + warningWWW.apply(null, args); + } } - } -} -function printWarning(level, format, args) { - { - var React = require("react"); + /** + * `ReactInstanceMap` maintains a mapping from a public facing stateful + * instance (key) and the internal representation (value). This allows public + * methods to accept the user facing instance as an argument and map them back + * to internal methods. + * + * Note that this module is currently shared and assumed to be stateless. + * If this becomes an actual Map, that will break. + */ + function get(key) { + return key._reactInternals; + } + function has(key) { + return key._reactInternals !== undefined; + } + function set(key, value) { + key._reactInternals = value; + } var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; + + // Re-export dynamic flags from the www version. + var dynamicFeatureFlags = require("ReactFeatureFlags"); + + var disableInputAttributeSyncing = + dynamicFeatureFlags.disableInputAttributeSyncing, + disableIEWorkarounds = dynamicFeatureFlags.disableIEWorkarounds, + enableTrustedTypesIntegration = + dynamicFeatureFlags.enableTrustedTypesIntegration, + replayFailedUnitOfWorkWithInvokeGuardedCallback = + dynamicFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback, + enableLegacyFBSupport = dynamicFeatureFlags.enableLegacyFBSupport, + enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, + enableUseRefAccessWarning = dynamicFeatureFlags.enableUseRefAccessWarning, + enableLazyContextPropagation = + dynamicFeatureFlags.enableLazyContextPropagation, + enableUnifiedSyncLane = dynamicFeatureFlags.enableUnifiedSyncLane, + enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, + enableCustomElementPropertySupport = + dynamicFeatureFlags.enableCustomElementPropertySupport, + enableDeferRootSchedulingToMicrotask = + dynamicFeatureFlags.enableDeferRootSchedulingToMicrotask, + enableAsyncActions = dynamicFeatureFlags.enableAsyncActions, + alwaysThrottleRetries = dynamicFeatureFlags.alwaysThrottleRetries, + enableDO_NOT_USE_disableStrictPassiveEffect = + dynamicFeatureFlags.enableDO_NOT_USE_disableStrictPassiveEffect, + disableSchedulerTimeoutInWorkLoop = + dynamicFeatureFlags.disableSchedulerTimeoutInWorkLoop, + enableUseDeferredValueInitialArg = + dynamicFeatureFlags.enableUseDeferredValueInitialArg; // On WWW, false is used for a new modern build. + var enableProfilerTimer = true; + var enableProfilerCommitHooks = true; + var enableProfilerNestedUpdatePhase = true; + var enableProfilerNestedUpdateScheduledHook = + dynamicFeatureFlags.enableProfilerNestedUpdateScheduledHook; + var createRootStrictEffectsByDefault = false; + var enableHostSingletons = true; + var enableClientRenderFallbackOnTextMismatch = false; + + var enableSchedulingProfiler = dynamicFeatureFlags.enableSchedulingProfiler; // Note: we'll want to remove this when we to userland implementation. + var enableFormActions = false; + var enableSuspenseCallback = true; + + var FunctionComponent = 0; + var ClassComponent = 1; + var IndeterminateComponent = 2; // Before we know whether it is function or class + + var HostRoot = 3; // Root of a host tree. Could be nested inside another node. + + var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. + + var HostComponent = 5; + var HostText = 6; + var Fragment = 7; + var Mode = 8; + var ContextConsumer = 9; + var ContextProvider = 10; + var ForwardRef = 11; + var Profiler = 12; + var SuspenseComponent = 13; + var MemoComponent = 14; + var SimpleMemoComponent = 15; + var LazyComponent = 16; + var IncompleteClassComponent = 17; + var DehydratedFragment = 18; + var SuspenseListComponent = 19; + var ScopeComponent = 21; + var OffscreenComponent = 22; + var LegacyHiddenComponent = 23; + var CacheComponent = 24; + var TracingMarkerComponent = 25; + var HostHoistable = 26; + var HostSingleton = 27; + + // ATTENTION + // When adding new symbols to this file, + // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' + // The Symbol used to tag the ReactElement-like types. + var REACT_ELEMENT_TYPE = Symbol.for("react.element"); + var REACT_PORTAL_TYPE = Symbol.for("react.portal"); + var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); + var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); + var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); + var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); + var REACT_CONTEXT_TYPE = Symbol.for("react.context"); + var REACT_SERVER_CONTEXT_TYPE = Symbol.for("react.server_context"); + var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); + var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); + var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); + var REACT_MEMO_TYPE = Symbol.for("react.memo"); + var REACT_LAZY_TYPE = Symbol.for("react.lazy"); + var REACT_SCOPE_TYPE = Symbol.for("react.scope"); + var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); + var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); + var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); + var REACT_CACHE_TYPE = Symbol.for("react.cache"); + var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); + var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel"); + var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; + var FAUX_ITERATOR_SYMBOL = "@@iterator"; + function getIteratorFn(maybeIterable) { + if (maybeIterable === null || typeof maybeIterable !== "object") { + return null; + } - if (ReactSharedInternals != null) { - var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - var stack = ReactDebugCurrentFrame.getStackAddendum(); + var maybeIterator = + (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || + maybeIterable[FAUX_ITERATOR_SYMBOL]; - if (stack !== "") { - format += "%s"; - args.push(stack); + if (typeof maybeIterator === "function") { + return maybeIterator; } - } // TODO: don't ignore level and pass it down somewhere too. - args.unshift(format); - args.unshift(false); - warningWWW.apply(null, args); - } -} + return null; + } -/** - * `ReactInstanceMap` maintains a mapping from a public facing stateful - * instance (key) and the internal representation (value). This allows public - * methods to accept the user facing instance as an argument and map them back - * to internal methods. - * - * Note that this module is currently shared and assumed to be stateless. - * If this becomes an actual Map, that will break. - */ -function get(key) { - return key._reactInternals; -} -function has(key) { - return key._reactInternals !== undefined; -} -function set(key, value) { - key._reactInternals = value; -} + function getWrappedName$1(outerType, innerType, wrapperName) { + var displayName = outerType.displayName; -var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; - -// Re-export dynamic flags from the www version. -var dynamicFeatureFlags = require("ReactFeatureFlags"); - -var disableInputAttributeSyncing = - dynamicFeatureFlags.disableInputAttributeSyncing, - disableIEWorkarounds = dynamicFeatureFlags.disableIEWorkarounds, - enableTrustedTypesIntegration = - dynamicFeatureFlags.enableTrustedTypesIntegration, - replayFailedUnitOfWorkWithInvokeGuardedCallback = - dynamicFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback, - enableLegacyFBSupport = dynamicFeatureFlags.enableLegacyFBSupport, - enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, - enableUseRefAccessWarning = dynamicFeatureFlags.enableUseRefAccessWarning, - enableLazyContextPropagation = - dynamicFeatureFlags.enableLazyContextPropagation, - enableUnifiedSyncLane = dynamicFeatureFlags.enableUnifiedSyncLane, - enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, - enableCustomElementPropertySupport = - dynamicFeatureFlags.enableCustomElementPropertySupport, - enableDeferRootSchedulingToMicrotask = - dynamicFeatureFlags.enableDeferRootSchedulingToMicrotask, - enableAsyncActions = dynamicFeatureFlags.enableAsyncActions, - alwaysThrottleRetries = dynamicFeatureFlags.alwaysThrottleRetries, - enableDO_NOT_USE_disableStrictPassiveEffect = - dynamicFeatureFlags.enableDO_NOT_USE_disableStrictPassiveEffect, - disableSchedulerTimeoutInWorkLoop = - dynamicFeatureFlags.disableSchedulerTimeoutInWorkLoop, - enableUseDeferredValueInitialArg = - dynamicFeatureFlags.enableUseDeferredValueInitialArg; // On WWW, false is used for a new modern build. -var enableProfilerTimer = true; -var enableProfilerCommitHooks = true; -var enableProfilerNestedUpdatePhase = true; -var enableProfilerNestedUpdateScheduledHook = - dynamicFeatureFlags.enableProfilerNestedUpdateScheduledHook; -var createRootStrictEffectsByDefault = false; -var enableHostSingletons = true; -var enableClientRenderFallbackOnTextMismatch = false; - -var enableSchedulingProfiler = dynamicFeatureFlags.enableSchedulingProfiler; // Note: we'll want to remove this when we to userland implementation. -var enableFormActions = false; -var enableSuspenseCallback = true; - -var FunctionComponent = 0; -var ClassComponent = 1; -var IndeterminateComponent = 2; // Before we know whether it is function or class - -var HostRoot = 3; // Root of a host tree. Could be nested inside another node. - -var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. - -var HostComponent = 5; -var HostText = 6; -var Fragment = 7; -var Mode = 8; -var ContextConsumer = 9; -var ContextProvider = 10; -var ForwardRef = 11; -var Profiler = 12; -var SuspenseComponent = 13; -var MemoComponent = 14; -var SimpleMemoComponent = 15; -var LazyComponent = 16; -var IncompleteClassComponent = 17; -var DehydratedFragment = 18; -var SuspenseListComponent = 19; -var ScopeComponent = 21; -var OffscreenComponent = 22; -var LegacyHiddenComponent = 23; -var CacheComponent = 24; -var TracingMarkerComponent = 25; -var HostHoistable = 26; -var HostSingleton = 27; - -// ATTENTION -// When adding new symbols to this file, -// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' -// The Symbol used to tag the ReactElement-like types. -var REACT_ELEMENT_TYPE = Symbol.for("react.element"); -var REACT_PORTAL_TYPE = Symbol.for("react.portal"); -var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); -var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); -var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); -var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); -var REACT_CONTEXT_TYPE = Symbol.for("react.context"); -var REACT_SERVER_CONTEXT_TYPE = Symbol.for("react.server_context"); -var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); -var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); -var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); -var REACT_MEMO_TYPE = Symbol.for("react.memo"); -var REACT_LAZY_TYPE = Symbol.for("react.lazy"); -var REACT_SCOPE_TYPE = Symbol.for("react.scope"); -var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); -var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); -var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); -var REACT_CACHE_TYPE = Symbol.for("react.cache"); -var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); -var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel"); -var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; -var FAUX_ITERATOR_SYMBOL = "@@iterator"; -function getIteratorFn(maybeIterable) { - if (maybeIterable === null || typeof maybeIterable !== "object") { - return null; - } - - var maybeIterator = - (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || - maybeIterable[FAUX_ITERATOR_SYMBOL]; - - if (typeof maybeIterator === "function") { - return maybeIterator; - } - - return null; -} + if (displayName) { + return displayName; + } -function getWrappedName$1(outerType, innerType, wrapperName) { - var displayName = outerType.displayName; - - if (displayName) { - return displayName; - } - - var functionName = innerType.displayName || innerType.name || ""; - return functionName !== "" - ? wrapperName + "(" + functionName + ")" - : wrapperName; -} // Keep in sync with react-reconciler/getComponentNameFromFiber - -function getContextName$1(type) { - return type.displayName || "Context"; -} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. - -function getComponentNameFromType(type) { - if (type == null) { - // Host root, text node or just invalid type. - return null; - } - - { - if (typeof type.tag === "number") { - error( - "Received an unexpected object in getComponentNameFromType(). " + - "This is likely a bug in React. Please file an issue." - ); - } - } + var functionName = innerType.displayName || innerType.name || ""; + return functionName !== "" + ? wrapperName + "(" + functionName + ")" + : wrapperName; + } // Keep in sync with react-reconciler/getComponentNameFromFiber + + function getContextName$1(type) { + return type.displayName || "Context"; + } // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. + + function getComponentNameFromType(type) { + if (type == null) { + // Host root, text node or just invalid type. + return null; + } + + { + if (typeof type.tag === "number") { + error( + "Received an unexpected object in getComponentNameFromType(). " + + "This is likely a bug in React. Please file an issue." + ); + } + } - if (typeof type === "function") { - return type.displayName || type.name || null; - } + if (typeof type === "function") { + return type.displayName || type.name || null; + } - if (typeof type === "string") { - return type; - } + if (typeof type === "string") { + return type; + } - switch (type) { - case REACT_FRAGMENT_TYPE: - return "Fragment"; + switch (type) { + case REACT_FRAGMENT_TYPE: + return "Fragment"; - case REACT_PORTAL_TYPE: - return "Portal"; + case REACT_PORTAL_TYPE: + return "Portal"; - case REACT_PROFILER_TYPE: - return "Profiler"; + case REACT_PROFILER_TYPE: + return "Profiler"; - case REACT_STRICT_MODE_TYPE: - return "StrictMode"; + case REACT_STRICT_MODE_TYPE: + return "StrictMode"; - case REACT_SUSPENSE_TYPE: - return "Suspense"; + case REACT_SUSPENSE_TYPE: + return "Suspense"; - case REACT_SUSPENSE_LIST_TYPE: - return "SuspenseList"; + case REACT_SUSPENSE_LIST_TYPE: + return "SuspenseList"; - case REACT_CACHE_TYPE: { - return "Cache"; - } + case REACT_CACHE_TYPE: { + return "Cache"; + } - // Fall through + // Fall through - case REACT_TRACING_MARKER_TYPE: - if (enableTransitionTracing) { - return "TracingMarker"; + case REACT_TRACING_MARKER_TYPE: + if (enableTransitionTracing) { + return "TracingMarker"; + } } - } - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_CONTEXT_TYPE: - var context = type; - return getContextName$1(context) + ".Consumer"; + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_CONTEXT_TYPE: + var context = type; + return getContextName$1(context) + ".Consumer"; - case REACT_PROVIDER_TYPE: - var provider = type; - return getContextName$1(provider._context) + ".Provider"; + case REACT_PROVIDER_TYPE: + var provider = type; + return getContextName$1(provider._context) + ".Provider"; - case REACT_FORWARD_REF_TYPE: - return getWrappedName$1(type, type.render, "ForwardRef"); + case REACT_FORWARD_REF_TYPE: + return getWrappedName$1(type, type.render, "ForwardRef"); - case REACT_MEMO_TYPE: - var outerName = type.displayName || null; + case REACT_MEMO_TYPE: + var outerName = type.displayName || null; - if (outerName !== null) { - return outerName; - } + if (outerName !== null) { + return outerName; + } - return getComponentNameFromType(type.type) || "Memo"; + return getComponentNameFromType(type.type) || "Memo"; - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - try { - return getComponentNameFromType(init(payload)); - } catch (x) { - return null; + try { + return getComponentNameFromType(init(payload)); + } catch (x) { + return null; + } + } } } + + return null; } - } - return null; -} + function getWrappedName(outerType, innerType, wrapperName) { + var functionName = innerType.displayName || innerType.name || ""; + return ( + outerType.displayName || + (functionName !== "" + ? wrapperName + "(" + functionName + ")" + : wrapperName) + ); + } // Keep in sync with shared/getComponentNameFromType -function getWrappedName(outerType, innerType, wrapperName) { - var functionName = innerType.displayName || innerType.name || ""; - return ( - outerType.displayName || - (functionName !== "" ? wrapperName + "(" + functionName + ")" : wrapperName) - ); -} // Keep in sync with shared/getComponentNameFromType + function getContextName(type) { + return type.displayName || "Context"; + } -function getContextName(type) { - return type.displayName || "Context"; -} + function getComponentNameFromFiber(fiber) { + var tag = fiber.tag, + type = fiber.type; -function getComponentNameFromFiber(fiber) { - var tag = fiber.tag, - type = fiber.type; + switch (tag) { + case CacheComponent: + return "Cache"; - switch (tag) { - case CacheComponent: - return "Cache"; + case ContextConsumer: + var context = type; + return getContextName(context) + ".Consumer"; - case ContextConsumer: - var context = type; - return getContextName(context) + ".Consumer"; + case ContextProvider: + var provider = type; + return getContextName(provider._context) + ".Provider"; - case ContextProvider: - var provider = type; - return getContextName(provider._context) + ".Provider"; + case DehydratedFragment: + return "DehydratedFragment"; - case DehydratedFragment: - return "DehydratedFragment"; + case ForwardRef: + return getWrappedName(type, type.render, "ForwardRef"); - case ForwardRef: - return getWrappedName(type, type.render, "ForwardRef"); + case Fragment: + return "Fragment"; - case Fragment: - return "Fragment"; + case HostHoistable: + case HostSingleton: + case HostComponent: + // Host component type is the display name (e.g. "div", "View") + return type; - case HostHoistable: - case HostSingleton: - case HostComponent: - // Host component type is the display name (e.g. "div", "View") - return type; + case HostPortal: + return "Portal"; - case HostPortal: - return "Portal"; + case HostRoot: + return "Root"; - case HostRoot: - return "Root"; + case HostText: + return "Text"; - case HostText: - return "Text"; + case LazyComponent: + // Name comes from the type in this case; we don't have a tag. + return getComponentNameFromType(type); - case LazyComponent: - // Name comes from the type in this case; we don't have a tag. - return getComponentNameFromType(type); + case Mode: + if (type === REACT_STRICT_MODE_TYPE) { + // Don't be less specific than shared/getComponentNameFromType + return "StrictMode"; + } - case Mode: - if (type === REACT_STRICT_MODE_TYPE) { - // Don't be less specific than shared/getComponentNameFromType - return "StrictMode"; - } + return "Mode"; - return "Mode"; + case OffscreenComponent: + return "Offscreen"; - case OffscreenComponent: - return "Offscreen"; + case Profiler: + return "Profiler"; - case Profiler: - return "Profiler"; + case ScopeComponent: + return "Scope"; - case ScopeComponent: - return "Scope"; + case SuspenseComponent: + return "Suspense"; - case SuspenseComponent: - return "Suspense"; + case SuspenseListComponent: + return "SuspenseList"; - case SuspenseListComponent: - return "SuspenseList"; + case TracingMarkerComponent: + return "TracingMarker"; + // The display name for this tags come from the user-provided type: - case TracingMarkerComponent: - return "TracingMarker"; - // The display name for this tags come from the user-provided type: + case ClassComponent: + case FunctionComponent: + case IncompleteClassComponent: + case IndeterminateComponent: + case MemoComponent: + case SimpleMemoComponent: + if (typeof type === "function") { + return type.displayName || type.name || null; + } - case ClassComponent: - case FunctionComponent: - case IncompleteClassComponent: - case IndeterminateComponent: - case MemoComponent: - case SimpleMemoComponent: - if (typeof type === "function") { - return type.displayName || type.name || null; - } + if (typeof type === "string") { + return type; + } - if (typeof type === "string") { - return type; - } + break; - break; + case LegacyHiddenComponent: { + return "LegacyHidden"; + } + } - case LegacyHiddenComponent: { - return "LegacyHidden"; + return null; } - } - return null; -} + var NoFlags$1 = + /* */ + 0; + var PerformedWork = + /* */ + 1; + var Placement = + /* */ + 2; + var DidCapture = + /* */ + 128; + var Hydrating = + /* */ + 4096; // You can change the rest (and add more). + + var Update = + /* */ + 4; + /* Skipped value: 0b0000000000000000000000001000; */ + + var ChildDeletion = + /* */ + 16; + var ContentReset = + /* */ + 32; + var Callback = + /* */ + 64; + /* Used by DidCapture: 0b0000000000000000000010000000; */ + + var ForceClientRender = + /* */ + 256; + var Ref = + /* */ + 512; + var Snapshot = + /* */ + 1024; + var Passive$1 = + /* */ + 2048; + /* Used by Hydrating: 0b0000000000000001000000000000; */ + + var Visibility = + /* */ + 8192; + var StoreConsistency = + /* */ + 16384; // It's OK to reuse these bits because these flags are mutually exclusive for + // different fiber types. We should really be doing this for as many flags as + // possible, because we're about to run out of bits. + + var ScheduleRetry = StoreConsistency; + var ShouldSuspendCommit = Visibility; + var LifecycleEffectMask = + Passive$1 | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit) + + var HostEffectMask = + /* */ + 32767; // These are not really side effects, but we still reuse this field. + + var Incomplete = + /* */ + 32768; + var ShouldCapture = + /* */ + 65536; + var ForceUpdateForLegacySuspense = + /* */ + 131072; + var DidPropagateContext = + /* */ + 262144; + var NeedsPropagation = + /* */ + 524288; + var Forked = + /* */ + 1048576; // Static tags describe aspects of a fiber that are not specific to a render, + // e.g. a fiber uses a passive effect (even if there are no updates on this particular render). + // This enables us to defer more work in the unmount case, + // since we can defer traversing the tree during layout to look for Passive effects, + // and instead rely on the static flag as a signal that there may be cleanup work. + + var RefStatic = + /* */ + 2097152; + var LayoutStatic = + /* */ + 4194304; + var PassiveStatic = + /* */ + 8388608; + var MaySuspendCommit = + /* */ + 16777216; // Flag used to identify newly inserted fibers. It isn't reset after commit unlike `Placement`. + + var PlacementDEV = + /* */ + 33554432; + var MountLayoutDev = + /* */ + 67108864; + var MountPassiveDev = + /* */ + 134217728; // Groups of flags that are used in the commit phase to skip over trees that + // don't contain effects, by checking subtreeFlags. + + var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility + // flag logic (see #20043) + Update | + Snapshot | // createEventHandle needs to visit deleted and hidden trees to + // fire beforeblur + // TODO: Only need to visit Deletions during BeforeMutation phase if an + // element is focused. + (ChildDeletion | Visibility); + var MutationMask = + Placement | + Update | + ChildDeletion | + ContentReset | + Ref | + Hydrating | + Visibility; + var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask + + var PassiveMask = Passive$1 | Visibility | ChildDeletion; // Union of tags that don't get reset on clones. + // This allows certain concepts to persist without recalculating them, + // e.g. whether a subtree contains passive effects or portals. + + var StaticMask = + LayoutStatic | PassiveStatic | RefStatic | MaySuspendCommit; + + var ReactCurrentOwner$3 = ReactSharedInternals.ReactCurrentOwner; + function getNearestMountedFiber(fiber) { + var node = fiber; + var nearestMounted = fiber; + + if (!fiber.alternate) { + // If there is no alternate, this might be a new tree that isn't inserted + // yet. If it is, then it will have a pending insertion effect on it. + var nextNode = node; -var NoFlags$1 = - /* */ - 0; -var PerformedWork = - /* */ - 1; -var Placement = - /* */ - 2; -var DidCapture = - /* */ - 128; -var Hydrating = - /* */ - 4096; // You can change the rest (and add more). - -var Update = - /* */ - 4; -/* Skipped value: 0b0000000000000000000000001000; */ - -var ChildDeletion = - /* */ - 16; -var ContentReset = - /* */ - 32; -var Callback = - /* */ - 64; -/* Used by DidCapture: 0b0000000000000000000010000000; */ - -var ForceClientRender = - /* */ - 256; -var Ref = - /* */ - 512; -var Snapshot = - /* */ - 1024; -var Passive$1 = - /* */ - 2048; -/* Used by Hydrating: 0b0000000000000001000000000000; */ - -var Visibility = - /* */ - 8192; -var StoreConsistency = - /* */ - 16384; // It's OK to reuse these bits because these flags are mutually exclusive for -// different fiber types. We should really be doing this for as many flags as -// possible, because we're about to run out of bits. - -var ScheduleRetry = StoreConsistency; -var ShouldSuspendCommit = Visibility; -var LifecycleEffectMask = - Passive$1 | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit) - -var HostEffectMask = - /* */ - 32767; // These are not really side effects, but we still reuse this field. - -var Incomplete = - /* */ - 32768; -var ShouldCapture = - /* */ - 65536; -var ForceUpdateForLegacySuspense = - /* */ - 131072; -var DidPropagateContext = - /* */ - 262144; -var NeedsPropagation = - /* */ - 524288; -var Forked = - /* */ - 1048576; // Static tags describe aspects of a fiber that are not specific to a render, -// e.g. a fiber uses a passive effect (even if there are no updates on this particular render). -// This enables us to defer more work in the unmount case, -// since we can defer traversing the tree during layout to look for Passive effects, -// and instead rely on the static flag as a signal that there may be cleanup work. - -var RefStatic = - /* */ - 2097152; -var LayoutStatic = - /* */ - 4194304; -var PassiveStatic = - /* */ - 8388608; -var MaySuspendCommit = - /* */ - 16777216; // Flag used to identify newly inserted fibers. It isn't reset after commit unlike `Placement`. - -var PlacementDEV = - /* */ - 33554432; -var MountLayoutDev = - /* */ - 67108864; -var MountPassiveDev = - /* */ - 134217728; // Groups of flags that are used in the commit phase to skip over trees that -// don't contain effects, by checking subtreeFlags. - -var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility - // flag logic (see #20043) - Update | - Snapshot | // createEventHandle needs to visit deleted and hidden trees to - // fire beforeblur - // TODO: Only need to visit Deletions during BeforeMutation phase if an - // element is focused. - (ChildDeletion | Visibility); -var MutationMask = - Placement | - Update | - ChildDeletion | - ContentReset | - Ref | - Hydrating | - Visibility; -var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask - -var PassiveMask = Passive$1 | Visibility | ChildDeletion; // Union of tags that don't get reset on clones. -// This allows certain concepts to persist without recalculating them, -// e.g. whether a subtree contains passive effects or portals. - -var StaticMask = LayoutStatic | PassiveStatic | RefStatic | MaySuspendCommit; - -var ReactCurrentOwner$3 = ReactSharedInternals.ReactCurrentOwner; -function getNearestMountedFiber(fiber) { - var node = fiber; - var nearestMounted = fiber; - - if (!fiber.alternate) { - // If there is no alternate, this might be a new tree that isn't inserted - // yet. If it is, then it will have a pending insertion effect on it. - var nextNode = node; - - do { - node = nextNode; - - if ((node.flags & (Placement | Hydrating)) !== NoFlags$1) { - // This is an insertion or in-progress hydration. The nearest possible - // mounted fiber is the parent but we need to continue to figure out - // if that one is still mounted. - nearestMounted = node.return; - } // $FlowFixMe[incompatible-type] we bail out when we get a null - - nextNode = node.return; - } while (nextNode); - } else { - while (node.return) { - node = node.return; - } - } - - if (node.tag === HostRoot) { - // TODO: Check if this was a nested HostRoot when used with - // renderContainerIntoSubtree. - return nearestMounted; - } // If we didn't hit the root, that means that we're in an disconnected tree - // that has been unmounted. - - return null; -} -function getSuspenseInstanceFromFiber(fiber) { - if (fiber.tag === SuspenseComponent) { - var suspenseState = fiber.memoizedState; + do { + node = nextNode; - if (suspenseState === null) { - var current = fiber.alternate; + if ((node.flags & (Placement | Hydrating)) !== NoFlags$1) { + // This is an insertion or in-progress hydration. The nearest possible + // mounted fiber is the parent but we need to continue to figure out + // if that one is still mounted. + nearestMounted = node.return; + } // $FlowFixMe[incompatible-type] we bail out when we get a null - if (current !== null) { - suspenseState = current.memoizedState; + nextNode = node.return; + } while (nextNode); + } else { + while (node.return) { + node = node.return; + } } - } - if (suspenseState !== null) { - return suspenseState.dehydrated; + if (node.tag === HostRoot) { + // TODO: Check if this was a nested HostRoot when used with + // renderContainerIntoSubtree. + return nearestMounted; + } // If we didn't hit the root, that means that we're in an disconnected tree + // that has been unmounted. + + return null; } - } + function getSuspenseInstanceFromFiber(fiber) { + if (fiber.tag === SuspenseComponent) { + var suspenseState = fiber.memoizedState; - return null; -} -function getContainerFromFiber(fiber) { - return fiber.tag === HostRoot ? fiber.stateNode.containerInfo : null; -} -function isFiberMounted(fiber) { - return getNearestMountedFiber(fiber) === fiber; -} -function isMounted(component) { - { - var owner = ReactCurrentOwner$3.current; + if (suspenseState === null) { + var current = fiber.alternate; - if (owner !== null && owner.tag === ClassComponent) { - var ownerFiber = owner; - var instance = ownerFiber.stateNode; + if (current !== null) { + suspenseState = current.memoizedState; + } + } - if (!instance._warnedAboutRefsInRender) { - 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" - ); + if (suspenseState !== null) { + return suspenseState.dehydrated; + } } - instance._warnedAboutRefsInRender = true; + return null; } - } - - var fiber = get(component); + function getContainerFromFiber(fiber) { + return fiber.tag === HostRoot ? fiber.stateNode.containerInfo : null; + } + function isFiberMounted(fiber) { + return getNearestMountedFiber(fiber) === fiber; + } + function isMounted(component) { + { + var owner = ReactCurrentOwner$3.current; - if (!fiber) { - return false; - } + if (owner !== null && owner.tag === ClassComponent) { + var ownerFiber = owner; + var instance = ownerFiber.stateNode; - return getNearestMountedFiber(fiber) === fiber; -} + if (!instance._warnedAboutRefsInRender) { + 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" + ); + } -function assertIsMounted(fiber) { - if (getNearestMountedFiber(fiber) !== fiber) { - throw new Error("Unable to find node on an unmounted component."); - } -} + instance._warnedAboutRefsInRender = true; + } + } -function findCurrentFiberUsingSlowPath(fiber) { - var alternate = fiber.alternate; + var fiber = get(component); - if (!alternate) { - // If there is no alternate, then we only need to check if it is mounted. - var nearestMounted = getNearestMountedFiber(fiber); + if (!fiber) { + return false; + } - if (nearestMounted === null) { - throw new Error("Unable to find node on an unmounted component."); + return getNearestMountedFiber(fiber) === fiber; } - if (nearestMounted !== fiber) { - return null; + function assertIsMounted(fiber) { + if (getNearestMountedFiber(fiber) !== fiber) { + throw new Error("Unable to find node on an unmounted component."); + } } - return fiber; - } // If we have two possible branches, we'll walk backwards up to the root - // to see what path the root points to. On the way we may hit one of the - // special cases and we'll deal with them. + function findCurrentFiberUsingSlowPath(fiber) { + var alternate = fiber.alternate; - var a = fiber; - var b = alternate; + if (!alternate) { + // If there is no alternate, then we only need to check if it is mounted. + var nearestMounted = getNearestMountedFiber(fiber); - while (true) { - var parentA = a.return; + if (nearestMounted === null) { + throw new Error("Unable to find node on an unmounted component."); + } - if (parentA === null) { - // We're at the root. - break; - } + if (nearestMounted !== fiber) { + return null; + } - var parentB = parentA.alternate; + return fiber; + } // If we have two possible branches, we'll walk backwards up to the root + // to see what path the root points to. On the way we may hit one of the + // special cases and we'll deal with them. - if (parentB === null) { - // There is no alternate. This is an unusual case. Currently, it only - // happens when a Suspense component is hidden. An extra fragment fiber - // is inserted in between the Suspense fiber and its children. Skip - // over this extra fragment fiber and proceed to the next parent. - var nextParent = parentA.return; + var a = fiber; + var b = alternate; - if (nextParent !== null) { - a = b = nextParent; - continue; - } // If there's no parent, we're at the root. + while (true) { + var parentA = a.return; + + if (parentA === null) { + // We're at the root. + break; + } - break; - } // If both copies of the parent fiber point to the same child, we can - // assume that the child is current. This happens when we bailout on low - // priority: the bailed out fiber's child reuses the current child. + var parentB = parentA.alternate; - if (parentA.child === parentB.child) { - var child = parentA.child; + if (parentB === null) { + // There is no alternate. This is an unusual case. Currently, it only + // happens when a Suspense component is hidden. An extra fragment fiber + // is inserted in between the Suspense fiber and its children. Skip + // over this extra fragment fiber and proceed to the next parent. + var nextParent = parentA.return; - while (child) { - if (child === a) { - // We've determined that A is the current branch. - assertIsMounted(parentA); - return fiber; - } + if (nextParent !== null) { + a = b = nextParent; + continue; + } // If there's no parent, we're at the root. - if (child === b) { - // We've determined that B is the current branch. - assertIsMounted(parentA); - return alternate; - } + break; + } // If both copies of the parent fiber point to the same child, we can + // assume that the child is current. This happens when we bailout on low + // priority: the bailed out fiber's child reuses the current child. + + if (parentA.child === parentB.child) { + var child = parentA.child; + + while (child) { + if (child === a) { + // We've determined that A is the current branch. + assertIsMounted(parentA); + return fiber; + } - child = child.sibling; - } // We should never have an alternate for any mounting node. So the only - // way this could possibly happen is if this was unmounted, if at all. + if (child === b) { + // We've determined that B is the current branch. + assertIsMounted(parentA); + return alternate; + } - throw new Error("Unable to find node on an unmounted component."); - } + child = child.sibling; + } // We should never have an alternate for any mounting node. So the only + // way this could possibly happen is if this was unmounted, if at all. - if (a.return !== b.return) { - // The return pointer of A and the return pointer of B point to different - // fibers. We assume that return pointers never criss-cross, so A must - // belong to the child set of A.return, and B must belong to the child - // set of B.return. - a = parentA; - b = parentB; - } else { - // The return pointers point to the same fiber. We'll have to use the - // default, slow path: scan the child sets of each parent alternate to see - // which child belongs to which set. - // - // Search parent A's child set - var didFindChild = false; - var _child = parentA.child; + throw new Error("Unable to find node on an unmounted component."); + } - while (_child) { - if (_child === a) { - didFindChild = true; + if (a.return !== b.return) { + // The return pointer of A and the return pointer of B point to different + // fibers. We assume that return pointers never criss-cross, so A must + // belong to the child set of A.return, and B must belong to the child + // set of B.return. a = parentA; b = parentB; - break; - } + } else { + // The return pointers point to the same fiber. We'll have to use the + // default, slow path: scan the child sets of each parent alternate to see + // which child belongs to which set. + // + // Search parent A's child set + var didFindChild = false; + var _child = parentA.child; + + while (_child) { + if (_child === a) { + didFindChild = true; + a = parentA; + b = parentB; + break; + } - if (_child === b) { - didFindChild = true; - b = parentA; - a = parentB; - break; - } + if (_child === b) { + didFindChild = true; + b = parentA; + a = parentB; + break; + } - _child = _child.sibling; - } + _child = _child.sibling; + } - if (!didFindChild) { - // Search parent B's child set - _child = parentB.child; + if (!didFindChild) { + // Search parent B's child set + _child = parentB.child; - while (_child) { - if (_child === a) { - didFindChild = true; - a = parentB; - b = parentA; - break; - } + while (_child) { + if (_child === a) { + didFindChild = true; + a = parentB; + b = parentA; + break; + } - if (_child === b) { - didFindChild = true; - b = parentB; - a = parentA; - break; - } + if (_child === b) { + didFindChild = true; + b = parentB; + a = parentA; + break; + } + + _child = _child.sibling; + } - _child = _child.sibling; + if (!didFindChild) { + 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." + ); + } + } } - if (!didFindChild) { + if (a.alternate !== b) { 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." + "Return fibers should always be each others' alternates. " + + "This error is likely caused by a bug in React. Please file an issue." ); } + } // If the root is not a host container, we're in a disconnected tree. I.e. + // unmounted. + + if (a.tag !== HostRoot) { + throw new Error("Unable to find node on an unmounted component."); } - } - if (a.alternate !== b) { - 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." - ); - } - } // If the root is not a host container, we're in a disconnected tree. I.e. - // unmounted. + if (a.stateNode.current === a) { + // We've determined that A is the current branch. + return fiber; + } // Otherwise B has to be current branch. - if (a.tag !== HostRoot) { - throw new Error("Unable to find node on an unmounted component."); - } + return alternate; + } + function findCurrentHostFiber(parent) { + var currentParent = findCurrentFiberUsingSlowPath(parent); + return currentParent !== null + ? findCurrentHostFiberImpl(currentParent) + : null; + } - if (a.stateNode.current === a) { - // We've determined that A is the current branch. - return fiber; - } // Otherwise B has to be current branch. + function findCurrentHostFiberImpl(node) { + // Next we'll drill down this component to find the first HostComponent/Text. + var tag = node.tag; - return alternate; -} -function findCurrentHostFiber(parent) { - var currentParent = findCurrentFiberUsingSlowPath(parent); - return currentParent !== null - ? findCurrentHostFiberImpl(currentParent) - : null; -} + if ( + tag === HostComponent || + tag === HostHoistable || + tag === HostSingleton || + tag === HostText + ) { + return node; + } -function findCurrentHostFiberImpl(node) { - // Next we'll drill down this component to find the first HostComponent/Text. - var tag = node.tag; + var child = node.child; - if ( - tag === HostComponent || - tag === HostHoistable || - tag === HostSingleton || - tag === HostText - ) { - return node; - } + while (child !== null) { + var match = findCurrentHostFiberImpl(child); - var child = node.child; + if (match !== null) { + return match; + } - while (child !== null) { - var match = findCurrentHostFiberImpl(child); + child = child.sibling; + } - if (match !== null) { - return match; + return null; } - child = child.sibling; - } - - return null; -} + function findCurrentHostFiberWithNoPortals(parent) { + var currentParent = findCurrentFiberUsingSlowPath(parent); + return currentParent !== null + ? findCurrentHostFiberWithNoPortalsImpl(currentParent) + : null; + } -function findCurrentHostFiberWithNoPortals(parent) { - var currentParent = findCurrentFiberUsingSlowPath(parent); - return currentParent !== null - ? findCurrentHostFiberWithNoPortalsImpl(currentParent) - : null; -} + function findCurrentHostFiberWithNoPortalsImpl(node) { + // Next we'll drill down this component to find the first HostComponent/Text. + var tag = node.tag; -function findCurrentHostFiberWithNoPortalsImpl(node) { - // Next we'll drill down this component to find the first HostComponent/Text. - var tag = node.tag; + if ( + tag === HostComponent || + tag === HostHoistable || + tag === HostSingleton || + tag === HostText + ) { + return node; + } - if ( - tag === HostComponent || - tag === HostHoistable || - tag === HostSingleton || - tag === HostText - ) { - return node; - } + var child = node.child; - var child = node.child; + while (child !== null) { + if (child.tag !== HostPortal) { + var match = findCurrentHostFiberWithNoPortalsImpl(child); - while (child !== null) { - if (child.tag !== HostPortal) { - var match = findCurrentHostFiberWithNoPortalsImpl(child); + if (match !== null) { + return match; + } + } - if (match !== null) { - return match; + child = child.sibling; } + + return null; } - child = child.sibling; - } + function isFiberSuspenseAndTimedOut(fiber) { + var memoizedState = fiber.memoizedState; + return ( + fiber.tag === SuspenseComponent && + memoizedState !== null && + memoizedState.dehydrated === null + ); + } + function doesFiberContain(parentFiber, childFiber) { + var node = childFiber; + var parentFiberAlternate = parentFiber.alternate; - return null; -} + while (node !== null) { + if (node === parentFiber || node === parentFiberAlternate) { + return true; + } -function isFiberSuspenseAndTimedOut(fiber) { - var memoizedState = fiber.memoizedState; - return ( - fiber.tag === SuspenseComponent && - memoizedState !== null && - memoizedState.dehydrated === null - ); -} -function doesFiberContain(parentFiber, childFiber) { - var node = childFiber; - var parentFiberAlternate = parentFiber.alternate; + node = node.return; + } - while (node !== null) { - if (node === parentFiber || node === parentFiberAlternate) { - return true; + return false; } - node = node.return; - } - - return false; -} + // This exists to avoid circular dependency between ReactDOMEventReplaying + // and DOMPluginEventSystem. + var currentReplayingEvent = null; + function setReplayingEvent(event) { + { + if (currentReplayingEvent !== null) { + error( + "Expected currently replaying event to be null. This error " + + "is likely caused by a bug in React. Please file an issue." + ); + } + } -// This exists to avoid circular dependency between ReactDOMEventReplaying -// and DOMPluginEventSystem. -var currentReplayingEvent = null; -function setReplayingEvent(event) { - { - if (currentReplayingEvent !== null) { - error( - "Expected currently replaying event to be null. This error " + - "is likely caused by a bug in React. Please file an issue." - ); + currentReplayingEvent = event; } - } - - currentReplayingEvent = event; -} -function resetReplayingEvent() { - { - if (currentReplayingEvent === null) { - error( - "Expected currently replaying event to not be null. This error " + - "is likely caused by a bug in React. Please file an issue." - ); + function resetReplayingEvent() { + { + if (currentReplayingEvent === null) { + error( + "Expected currently replaying event to not be null. This error " + + "is likely caused by a bug in React. Please file an issue." + ); + } + } + + currentReplayingEvent = null; + } + function isReplayingEvent(event) { + return event === currentReplayingEvent; } - } - currentReplayingEvent = null; -} -function isReplayingEvent(event) { - return event === currentReplayingEvent; -} + function useFormStatus() { + { + throw new Error("Not implemented."); + } + } + function useFormState(action, initialState, permalink) { + { + throw new Error("Not implemented."); + } + } -function useFormStatus() { - { - throw new Error("Not implemented."); - } -} -function useFormState(action, initialState, permalink) { - { - throw new Error("Not implemented."); - } -} + var valueStack = []; + var fiberStack; -var valueStack = []; -var fiberStack; + { + fiberStack = []; + } -{ - fiberStack = []; -} + var index = -1; -var index = -1; + function createCursor(defaultValue) { + return { + current: defaultValue + }; + } -function createCursor(defaultValue) { - return { - current: defaultValue - }; -} + function pop(cursor, fiber) { + if (index < 0) { + { + error("Unexpected pop."); + } -function pop(cursor, fiber) { - if (index < 0) { - { - error("Unexpected pop."); - } + return; + } - return; - } + { + if (fiber !== fiberStack[index]) { + error("Unexpected Fiber popped."); + } + } + + cursor.current = valueStack[index]; + valueStack[index] = null; - { - if (fiber !== fiberStack[index]) { - error("Unexpected Fiber popped."); + { + fiberStack[index] = null; + } + + index--; } - } - cursor.current = valueStack[index]; - valueStack[index] = null; + function push(cursor, value, fiber) { + index++; + valueStack[index] = cursor.current; - { - fiberStack[index] = null; - } + { + fiberStack[index] = fiber; + } - index--; -} + cursor.current = value; + } -function push(cursor, value, fiber) { - index++; - valueStack[index] = cursor.current; + var contextStackCursor$1 = createCursor(null); + var contextFiberStackCursor = createCursor(null); + var rootInstanceStackCursor = createCursor(null); // Represents the nearest host transition provider (in React DOM, a ) - { - fiberStack[index] = fiber; - } + function requiredContext(c) { + { + if (c === null) { + error( + "Expected host context to exist. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + } + } - cursor.current = value; -} + return c; + } -var contextStackCursor$1 = createCursor(null); -var contextFiberStackCursor = createCursor(null); -var rootInstanceStackCursor = createCursor(null); // Represents the nearest host transition provider (in React DOM, a ) + function getCurrentRootHostContainer() { + return rootInstanceStackCursor.current; + } -function requiredContext(c) { - { - if (c === null) { - error( - "Expected host context to exist. This error is likely caused by a bug " + - "in React. Please file an issue." - ); + function getRootHostContainer() { + var rootInstance = requiredContext(rootInstanceStackCursor.current); + return rootInstance; } - } - return c; -} + function pushHostContainer(fiber, nextRootInstance) { + // Push current root instance onto the stack; + // This allows us to reset root when portals are popped. + push(rootInstanceStackCursor, nextRootInstance, fiber); // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. -function getCurrentRootHostContainer() { - return rootInstanceStackCursor.current; -} + push(contextFiberStackCursor, fiber, fiber); // Finally, we need to push the host context to the stack. + // However, we can't just call getRootHostContext() and push it because + // we'd have a different number of entries on the stack depending on + // whether getRootHostContext() throws somewhere in renderer code or not. + // So we push an empty value first. This lets us safely unwind on errors. -function getRootHostContainer() { - var rootInstance = requiredContext(rootInstanceStackCursor.current); - return rootInstance; -} + push(contextStackCursor$1, null, fiber); + var nextRootContext = getRootHostContext(nextRootInstance); // Now that we know this function doesn't throw, replace it. -function pushHostContainer(fiber, nextRootInstance) { - // Push current root instance onto the stack; - // This allows us to reset root when portals are popped. - push(rootInstanceStackCursor, nextRootInstance, fiber); // Track the context and the Fiber that provided it. - // This enables us to pop only Fibers that provide unique contexts. + pop(contextStackCursor$1, fiber); + push(contextStackCursor$1, nextRootContext, fiber); + } - push(contextFiberStackCursor, fiber, fiber); // Finally, we need to push the host context to the stack. - // However, we can't just call getRootHostContext() and push it because - // we'd have a different number of entries on the stack depending on - // whether getRootHostContext() throws somewhere in renderer code or not. - // So we push an empty value first. This lets us safely unwind on errors. + function popHostContainer(fiber) { + pop(contextStackCursor$1, fiber); + pop(contextFiberStackCursor, fiber); + pop(rootInstanceStackCursor, fiber); + } - push(contextStackCursor$1, null, fiber); - var nextRootContext = getRootHostContext(nextRootInstance); // Now that we know this function doesn't throw, replace it. + function getHostContext() { + var context = requiredContext(contextStackCursor$1.current); + return context; + } - pop(contextStackCursor$1, fiber); - push(contextStackCursor$1, nextRootContext, fiber); -} + function pushHostContext(fiber) { + var context = requiredContext(contextStackCursor$1.current); + var nextContext = getChildHostContext(context, fiber.type); // Don't push this Fiber's context unless it's unique. -function popHostContainer(fiber) { - pop(contextStackCursor$1, fiber); - pop(contextFiberStackCursor, fiber); - pop(rootInstanceStackCursor, fiber); -} + if (context !== nextContext) { + // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. + push(contextFiberStackCursor, fiber, fiber); + push(contextStackCursor$1, nextContext, fiber); + } + } -function getHostContext() { - var context = requiredContext(contextStackCursor$1.current); - return context; -} + function popHostContext(fiber) { + if (contextFiberStackCursor.current === fiber) { + // Do not pop unless this Fiber provided the current context. + // pushHostContext() only pushes Fibers that provide unique contexts. + pop(contextStackCursor$1, fiber); + pop(contextFiberStackCursor, fiber); + } + } -function pushHostContext(fiber) { - var context = requiredContext(contextStackCursor$1.current); - var nextContext = getChildHostContext(context, fiber.type); // Don't push this Fiber's context unless it's unique. + // This module only exists as an ESM wrapper around the external CommonJS + var scheduleCallback$3 = Scheduler.unstable_scheduleCallback; + var cancelCallback$1 = Scheduler.unstable_cancelCallback; + var shouldYield = Scheduler.unstable_shouldYield; + var requestPaint = Scheduler.unstable_requestPaint; + var now$1 = Scheduler.unstable_now; + var getCurrentPriorityLevel = Scheduler.unstable_getCurrentPriorityLevel; + var ImmediatePriority = Scheduler.unstable_ImmediatePriority; + var UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; + var NormalPriority$1 = Scheduler.unstable_NormalPriority; + var LowPriority = Scheduler.unstable_LowPriority; + var IdlePriority = Scheduler.unstable_IdlePriority; // this doesn't actually exist on the scheduler, but it *does* + // on scheduler/unstable_mock, which we'll need for internal testing - if (context !== nextContext) { - // Track the context and the Fiber that provided it. - // This enables us to pop only Fibers that provide unique contexts. - push(contextFiberStackCursor, fiber, fiber); - push(contextStackCursor$1, nextContext, fiber); - } -} + var log$2 = Scheduler.log; + var unstable_setDisableYieldValue = Scheduler.unstable_setDisableYieldValue; -function popHostContext(fiber) { - if (contextFiberStackCursor.current === fiber) { - // Do not pop unless this Fiber provided the current context. - // pushHostContext() only pushes Fibers that provide unique contexts. - pop(contextStackCursor$1, fiber); - pop(contextFiberStackCursor, fiber); - } -} + // Helpers to patch console.logs to avoid logging during side-effect free + // replaying on render function. This currently only patches the object + // lazily which won't cover if the log function was extracted eagerly. + // We could also eagerly patch the method. + var disabledDepth = 0; + var prevLog; + var prevInfo; + var prevWarn; + var prevError; + var prevGroup; + var prevGroupCollapsed; + var prevGroupEnd; -// This module only exists as an ESM wrapper around the external CommonJS -var scheduleCallback$3 = Scheduler.unstable_scheduleCallback; -var cancelCallback$1 = Scheduler.unstable_cancelCallback; -var shouldYield = Scheduler.unstable_shouldYield; -var requestPaint = Scheduler.unstable_requestPaint; -var now$1 = Scheduler.unstable_now; -var getCurrentPriorityLevel = Scheduler.unstable_getCurrentPriorityLevel; -var ImmediatePriority = Scheduler.unstable_ImmediatePriority; -var UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; -var NormalPriority$1 = Scheduler.unstable_NormalPriority; -var LowPriority = Scheduler.unstable_LowPriority; -var IdlePriority = Scheduler.unstable_IdlePriority; // this doesn't actually exist on the scheduler, but it *does* -// on scheduler/unstable_mock, which we'll need for internal testing - -var log$2 = Scheduler.log; -var unstable_setDisableYieldValue = Scheduler.unstable_setDisableYieldValue; - -// Helpers to patch console.logs to avoid logging during side-effect free -// replaying on render function. This currently only patches the object -// lazily which won't cover if the log function was extracted eagerly. -// We could also eagerly patch the method. -var disabledDepth = 0; -var prevLog; -var prevInfo; -var prevWarn; -var prevError; -var prevGroup; -var prevGroupCollapsed; -var prevGroupEnd; - -function disabledLog() {} - -disabledLog.__reactDisabledLog = true; -function disableLogs() { - { - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - prevLog = console.log; - prevInfo = console.info; - prevWarn = console.warn; - prevError = console.error; - prevGroup = console.group; - prevGroupCollapsed = console.groupCollapsed; - prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 - - var props = { - configurable: true, - enumerable: true, - value: disabledLog, - writable: true - }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. - - Object.defineProperties(console, { - info: props, - log: props, - warn: props, - error: props, - group: props, - groupCollapsed: props, - groupEnd: props - }); - /* eslint-enable react-internal/no-production-logging */ - } + function disabledLog() {} - disabledDepth++; - } -} -function reenableLogs() { - { - disabledDepth--; + disabledLog.__reactDisabledLog = true; + function disableLogs() { + { + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + prevLog = console.log; + prevInfo = console.info; + prevWarn = console.warn; + prevError = console.error; + prevGroup = console.group; + prevGroupCollapsed = console.groupCollapsed; + prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 + + var props = { + configurable: true, + enumerable: true, + value: disabledLog, + writable: true + }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. + + Object.defineProperties(console, { + info: props, + log: props, + warn: props, + error: props, + group: props, + groupCollapsed: props, + groupEnd: props + }); + /* eslint-enable react-internal/no-production-logging */ + } - if (disabledDepth === 0) { - /* eslint-disable react-internal/no-production-logging */ - var props = { - configurable: true, - enumerable: true, - writable: true - }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. - - Object.defineProperties(console, { - log: assign({}, props, { - value: prevLog - }), - info: assign({}, props, { - value: prevInfo - }), - warn: assign({}, props, { - value: prevWarn - }), - error: assign({}, props, { - value: prevError - }), - group: assign({}, props, { - value: prevGroup - }), - groupCollapsed: assign({}, props, { - value: prevGroupCollapsed - }), - groupEnd: assign({}, props, { - value: prevGroupEnd - }) - }); - /* eslint-enable react-internal/no-production-logging */ + disabledDepth++; + } } + function reenableLogs() { + { + disabledDepth--; + + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + var props = { + configurable: true, + enumerable: true, + writable: true + }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. + + Object.defineProperties(console, { + log: assign({}, props, { + value: prevLog + }), + info: assign({}, props, { + value: prevInfo + }), + warn: assign({}, props, { + value: prevWarn + }), + error: assign({}, props, { + value: prevError + }), + group: assign({}, props, { + value: prevGroup + }), + groupCollapsed: assign({}, props, { + value: prevGroupCollapsed + }), + groupEnd: assign({}, props, { + value: prevGroupEnd + }) + }); + /* eslint-enable react-internal/no-production-logging */ + } - if (disabledDepth < 0) { - error( - "disabledDepth fell below zero. " + - "This is a bug in React. Please file an issue." - ); + if (disabledDepth < 0) { + error( + "disabledDepth fell below zero. " + + "This is a bug in React. Please file an issue." + ); + } + } } - } -} -var rendererID = null; -var injectedHook = null; -var injectedProfilingHooks = null; -var hasLoggedError = false; -var isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined"; -function injectInternals(internals) { - if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { - // No DevTools - return false; - } - - var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - - if (hook.isDisabled) { - // This isn't a real property on the hook, but it can be set to opt out - // of DevTools integration and associated warnings and logs. - // https://github.com/facebook/react/issues/3877 - return true; - } - - if (!hook.supportsFiber) { - { - 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" - ); - } // DevTools exists, even though it doesn't support Fiber. - - return true; - } - - try { - if (enableSchedulingProfiler) { - // Conditionally inject these hooks only if Timeline profiler is supported by this build. - // This gives DevTools a way to feature detect that isn't tied to version number - // (since profiling and timeline are controlled by different feature flags). - internals = assign({}, internals, { - getLaneLabelMap: getLaneLabelMap, - injectProfilingHooks: injectProfilingHooks - }); - } + var rendererID = null; + var injectedHook = null; + var injectedProfilingHooks = null; + var hasLoggedError = false; + var isDevToolsPresent = + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined"; + function injectInternals(internals) { + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { + // No DevTools + return false; + } - rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - injectedHook = hook; - } catch (err) { - // Catch all errors because it is unsafe to throw during initialization. - { - error("React instrumentation encountered an error: %s.", err); - } - } + if (hook.isDisabled) { + // This isn't a real property on the hook, but it can be set to opt out + // of DevTools integration and associated warnings and logs. + // https://github.com/facebook/react/issues/3877 + return true; + } + + if (!hook.supportsFiber) { + { + 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" + ); + } // DevTools exists, even though it doesn't support Fiber. + + return true; + } - if (hook.checkDCE) { - // This is the real DevTools. - return true; - } else { - // This is likely a hook installed by Fast Refresh runtime. - return false; - } -} -function onScheduleRoot(root, children) { - { - if ( - injectedHook && - typeof injectedHook.onScheduleFiberRoot === "function" - ) { try { - injectedHook.onScheduleFiberRoot(rendererID, root, children); + if (enableSchedulingProfiler) { + // Conditionally inject these hooks only if Timeline profiler is supported by this build. + // This gives DevTools a way to feature detect that isn't tied to version number + // (since profiling and timeline are controlled by different feature flags). + internals = assign({}, internals, { + getLaneLabelMap: getLaneLabelMap, + injectProfilingHooks: injectProfilingHooks + }); + } + + rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. + + injectedHook = hook; } catch (err) { - if (!hasLoggedError) { - hasLoggedError = true; + // Catch all errors because it is unsafe to throw during initialization. + { + error("React instrumentation encountered an error: %s.", err); + } + } + + if (hook.checkDCE) { + // This is the real DevTools. + return true; + } else { + // This is likely a hook installed by Fast Refresh runtime. + return false; + } + } + function onScheduleRoot(root, children) { + { + if ( + injectedHook && + typeof injectedHook.onScheduleFiberRoot === "function" + ) { + try { + injectedHook.onScheduleFiberRoot(rendererID, root, children); + } catch (err) { + if (!hasLoggedError) { + hasLoggedError = true; - error("React instrumentation encountered an error: %s", err); + error("React instrumentation encountered an error: %s", err); + } + } } } } - } -} -function onCommitRoot$1(root, eventPriority) { - if (injectedHook && typeof injectedHook.onCommitFiberRoot === "function") { - try { - var didError = (root.current.flags & DidCapture) === DidCapture; + function onCommitRoot$1(root, eventPriority) { + if ( + injectedHook && + typeof injectedHook.onCommitFiberRoot === "function" + ) { + try { + var didError = (root.current.flags & DidCapture) === DidCapture; - if (enableProfilerTimer) { - var schedulerPriority; + if (enableProfilerTimer) { + var schedulerPriority; - switch (eventPriority) { - case DiscreteEventPriority: - schedulerPriority = ImmediatePriority; - break; + switch (eventPriority) { + case DiscreteEventPriority: + schedulerPriority = ImmediatePriority; + break; - case ContinuousEventPriority: - schedulerPriority = UserBlockingPriority; - break; + case ContinuousEventPriority: + schedulerPriority = UserBlockingPriority; + break; - case DefaultEventPriority: - schedulerPriority = NormalPriority$1; - break; + case DefaultEventPriority: + schedulerPriority = NormalPriority$1; + break; - case IdleEventPriority: - schedulerPriority = IdlePriority; - break; + case IdleEventPriority: + schedulerPriority = IdlePriority; + break; - default: - schedulerPriority = NormalPriority$1; - break; - } + default: + schedulerPriority = NormalPriority$1; + break; + } - injectedHook.onCommitFiberRoot( - rendererID, - root, - schedulerPriority, - didError - ); - } - } catch (err) { - { - if (!hasLoggedError) { - hasLoggedError = true; + injectedHook.onCommitFiberRoot( + rendererID, + root, + schedulerPriority, + didError + ); + } + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; - error("React instrumentation encountered an error: %s", err); + error("React instrumentation encountered an error: %s", err); + } + } } } } - } -} -function onPostCommitRoot(root) { - if ( - injectedHook && - typeof injectedHook.onPostCommitFiberRoot === "function" - ) { - try { - injectedHook.onPostCommitFiberRoot(rendererID, root); - } catch (err) { - { - if (!hasLoggedError) { - hasLoggedError = true; + function onPostCommitRoot(root) { + if ( + injectedHook && + typeof injectedHook.onPostCommitFiberRoot === "function" + ) { + try { + injectedHook.onPostCommitFiberRoot(rendererID, root); + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; - error("React instrumentation encountered an error: %s", err); + error("React instrumentation encountered an error: %s", err); + } + } } } } - } -} -function onCommitUnmount(fiber) { - if (injectedHook && typeof injectedHook.onCommitFiberUnmount === "function") { - try { - injectedHook.onCommitFiberUnmount(rendererID, fiber); - } catch (err) { - { - if (!hasLoggedError) { - hasLoggedError = true; + function onCommitUnmount(fiber) { + if ( + injectedHook && + typeof injectedHook.onCommitFiberUnmount === "function" + ) { + try { + injectedHook.onCommitFiberUnmount(rendererID, fiber); + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; - error("React instrumentation encountered an error: %s", err); + error("React instrumentation encountered an error: %s", err); + } + } } } } - } -} -function setIsStrictModeForDevtools(newIsStrictMode) { - { - if (typeof log$2 === "function") { - // We're in a test because Scheduler.log only exists - // in SchedulerMock. To reduce the noise in strict mode tests, - // suppress warnings and disable scheduler yielding during the double render - unstable_setDisableYieldValue(newIsStrictMode); - setSuppressWarning(newIsStrictMode); - } + function setIsStrictModeForDevtools(newIsStrictMode) { + { + if (typeof log$2 === "function") { + // We're in a test because Scheduler.log only exists + // in SchedulerMock. To reduce the noise in strict mode tests, + // suppress warnings and disable scheduler yielding during the double render + unstable_setDisableYieldValue(newIsStrictMode); + setSuppressWarning(newIsStrictMode); + } - if (injectedHook && typeof injectedHook.setStrictMode === "function") { - try { - injectedHook.setStrictMode(rendererID, newIsStrictMode); - } catch (err) { - { - if (!hasLoggedError) { - hasLoggedError = true; + if (injectedHook && typeof injectedHook.setStrictMode === "function") { + try { + injectedHook.setStrictMode(rendererID, newIsStrictMode); + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; - error("React instrumentation encountered an error: %s", err); + error("React instrumentation encountered an error: %s", err); + } + } } } } + } // Profiler API hooks + + function injectProfilingHooks(profilingHooks) { + injectedProfilingHooks = profilingHooks; } - } -} // Profiler API hooks -function injectProfilingHooks(profilingHooks) { - injectedProfilingHooks = profilingHooks; -} + function getLaneLabelMap() { + if (enableSchedulingProfiler) { + var map = new Map(); + var lane = 1; -function getLaneLabelMap() { - if (enableSchedulingProfiler) { - var map = new Map(); - var lane = 1; + for (var index = 0; index < TotalLanes; index++) { + var label = getLabelForLane(lane); + map.set(lane, label); + lane *= 2; + } - for (var index = 0; index < TotalLanes; index++) { - var label = getLabelForLane(lane); - map.set(lane, label); - lane *= 2; + return map; + } else { + return null; + } } - return map; - } else { - return null; - } -} - -function markCommitStarted(lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markCommitStarted === "function" - ) { - injectedProfilingHooks.markCommitStarted(lanes); - } - } -} -function markCommitStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markCommitStopped === "function" - ) { - injectedProfilingHooks.markCommitStopped(); + function markCommitStarted(lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markCommitStarted === "function" + ) { + injectedProfilingHooks.markCommitStarted(lanes); + } + } } - } -} -function markComponentRenderStarted(fiber) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentRenderStarted === "function" - ) { - injectedProfilingHooks.markComponentRenderStarted(fiber); + function markCommitStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markCommitStopped === "function" + ) { + injectedProfilingHooks.markCommitStopped(); + } + } } - } -} -function markComponentRenderStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentRenderStopped === "function" - ) { - injectedProfilingHooks.markComponentRenderStopped(); + function markComponentRenderStarted(fiber) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentRenderStarted === + "function" + ) { + injectedProfilingHooks.markComponentRenderStarted(fiber); + } + } } - } -} -function markComponentPassiveEffectMountStarted(fiber) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectMountStarted === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectMountStarted(fiber); + function markComponentRenderStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentRenderStopped === + "function" + ) { + injectedProfilingHooks.markComponentRenderStopped(); + } + } } - } -} -function markComponentPassiveEffectMountStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectMountStopped === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectMountStopped(); + function markComponentPassiveEffectMountStarted(fiber) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectMountStarted === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectMountStarted(fiber); + } + } } - } -} -function markComponentPassiveEffectUnmountStarted(fiber) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStarted === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectUnmountStarted(fiber); + function markComponentPassiveEffectMountStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectMountStopped === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectMountStopped(); + } + } } - } -} -function markComponentPassiveEffectUnmountStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStopped === - "function" - ) { - injectedProfilingHooks.markComponentPassiveEffectUnmountStopped(); + function markComponentPassiveEffectUnmountStarted(fiber) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStarted === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectUnmountStarted( + fiber + ); + } + } } - } -} -function markComponentLayoutEffectMountStarted(fiber) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectMountStarted === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectMountStarted(fiber); + function markComponentPassiveEffectUnmountStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStopped === + "function" + ) { + injectedProfilingHooks.markComponentPassiveEffectUnmountStopped(); + } + } } - } -} -function markComponentLayoutEffectMountStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectMountStopped === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectMountStopped(); + function markComponentLayoutEffectMountStarted(fiber) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectMountStarted === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectMountStarted(fiber); + } + } } - } -} -function markComponentLayoutEffectUnmountStarted(fiber) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber); + function markComponentLayoutEffectMountStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectMountStopped === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectMountStopped(); + } + } } - } -} -function markComponentLayoutEffectUnmountStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped === - "function" - ) { - injectedProfilingHooks.markComponentLayoutEffectUnmountStopped(); + function markComponentLayoutEffectUnmountStarted(fiber) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber); + } + } } - } -} -function markComponentErrored(fiber, thrownValue, lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentErrored === "function" - ) { - injectedProfilingHooks.markComponentErrored(fiber, thrownValue, lanes); + function markComponentLayoutEffectUnmountStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped === + "function" + ) { + injectedProfilingHooks.markComponentLayoutEffectUnmountStopped(); + } + } } - } -} -function markComponentSuspended(fiber, wakeable, lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markComponentSuspended === "function" - ) { - injectedProfilingHooks.markComponentSuspended(fiber, wakeable, lanes); + function markComponentErrored(fiber, thrownValue, lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentErrored === "function" + ) { + injectedProfilingHooks.markComponentErrored( + fiber, + thrownValue, + lanes + ); + } + } } - } -} -function markLayoutEffectsStarted(lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markLayoutEffectsStarted === "function" - ) { - injectedProfilingHooks.markLayoutEffectsStarted(lanes); + function markComponentSuspended(fiber, wakeable, lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markComponentSuspended === "function" + ) { + injectedProfilingHooks.markComponentSuspended(fiber, wakeable, lanes); + } + } } - } -} -function markLayoutEffectsStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markLayoutEffectsStopped === "function" - ) { - injectedProfilingHooks.markLayoutEffectsStopped(); + function markLayoutEffectsStarted(lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markLayoutEffectsStarted === "function" + ) { + injectedProfilingHooks.markLayoutEffectsStarted(lanes); + } + } } - } -} -function markPassiveEffectsStarted(lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markPassiveEffectsStarted === "function" - ) { - injectedProfilingHooks.markPassiveEffectsStarted(lanes); + function markLayoutEffectsStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markLayoutEffectsStopped === "function" + ) { + injectedProfilingHooks.markLayoutEffectsStopped(); + } + } } - } -} -function markPassiveEffectsStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markPassiveEffectsStopped === "function" - ) { - injectedProfilingHooks.markPassiveEffectsStopped(); + function markPassiveEffectsStarted(lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markPassiveEffectsStarted === "function" + ) { + injectedProfilingHooks.markPassiveEffectsStarted(lanes); + } + } } - } -} -function markRenderStarted(lanes) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderStarted === "function" - ) { - injectedProfilingHooks.markRenderStarted(lanes); + function markPassiveEffectsStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markPassiveEffectsStopped === "function" + ) { + injectedProfilingHooks.markPassiveEffectsStopped(); + } + } } - } -} -function markRenderYielded() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderYielded === "function" - ) { - injectedProfilingHooks.markRenderYielded(); + function markRenderStarted(lanes) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderStarted === "function" + ) { + injectedProfilingHooks.markRenderStarted(lanes); + } + } } - } -} -function markRenderStopped() { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderStopped === "function" - ) { - injectedProfilingHooks.markRenderStopped(); + function markRenderYielded() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderYielded === "function" + ) { + injectedProfilingHooks.markRenderYielded(); + } + } } - } -} -function markRenderScheduled(lane) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markRenderScheduled === "function" - ) { - injectedProfilingHooks.markRenderScheduled(lane); + function markRenderStopped() { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderStopped === "function" + ) { + injectedProfilingHooks.markRenderStopped(); + } + } } - } -} -function markForceUpdateScheduled(fiber, lane) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markForceUpdateScheduled === "function" - ) { - injectedProfilingHooks.markForceUpdateScheduled(fiber, lane); + function markRenderScheduled(lane) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markRenderScheduled === "function" + ) { + injectedProfilingHooks.markRenderScheduled(lane); + } + } } - } -} -function markStateUpdateScheduled(fiber, lane) { - if (enableSchedulingProfiler) { - if ( - injectedProfilingHooks !== null && - typeof injectedProfilingHooks.markStateUpdateScheduled === "function" - ) { - injectedProfilingHooks.markStateUpdateScheduled(fiber, lane); + function markForceUpdateScheduled(fiber, lane) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markForceUpdateScheduled === "function" + ) { + injectedProfilingHooks.markForceUpdateScheduled(fiber, lane); + } + } } - } -} + function markStateUpdateScheduled(fiber, lane) { + if (enableSchedulingProfiler) { + if ( + injectedProfilingHooks !== null && + typeof injectedProfilingHooks.markStateUpdateScheduled === "function" + ) { + injectedProfilingHooks.markStateUpdateScheduled(fiber, lane); + } + } + } + + var NoMode = + /* */ + 0; // TODO: Remove ConcurrentMode by reading from the root tag instead + + var ConcurrentMode = + /* */ + 1; + var ProfileMode = + /* */ + 2; + var DebugTracingMode = + /* */ + 4; + var StrictLegacyMode = + /* */ + 8; + var StrictEffectsMode = + /* */ + 16; + var ConcurrentUpdatesByDefaultMode = + /* */ + 32; + var NoStrictPassiveEffectsMode = + /* */ + 64; + + // TODO: This is pretty well supported by browsers. Maybe we can drop it. + var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; // Count leading zeros. + // Based on: + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 + + var log$1 = Math.log; + var LN2 = Math.LN2; + + function clz32Fallback(x) { + var asUint = x >>> 0; + + if (asUint === 0) { + return 32; + } + + return (31 - ((log$1(asUint) / LN2) | 0)) | 0; + } + + // If those values are changed that package should be rebuilt and redeployed. + + var TotalLanes = 31; + var NoLanes = + /* */ + 0; + var NoLane = + /* */ + 0; + var SyncHydrationLane = + /* */ + 1; + var SyncLane = + /* */ + 2; + var SyncLaneIndex = 1; + var InputContinuousHydrationLane = + /* */ + 4; + var InputContinuousLane = + /* */ + 8; + var DefaultHydrationLane = + /* */ + 16; + var DefaultLane = + /* */ + 32; + var SyncUpdateLanes = enableUnifiedSyncLane + ? SyncLane | InputContinuousLane | DefaultLane + : SyncLane; + var TransitionHydrationLane = + /* */ + 64; + var TransitionLanes = + /* */ + 4194176; + var TransitionLane1 = + /* */ + 128; + var TransitionLane2 = + /* */ + 256; + var TransitionLane3 = + /* */ + 512; + var TransitionLane4 = + /* */ + 1024; + var TransitionLane5 = + /* */ + 2048; + var TransitionLane6 = + /* */ + 4096; + var TransitionLane7 = + /* */ + 8192; + var TransitionLane8 = + /* */ + 16384; + var TransitionLane9 = + /* */ + 32768; + var TransitionLane10 = + /* */ + 65536; + var TransitionLane11 = + /* */ + 131072; + var TransitionLane12 = + /* */ + 262144; + var TransitionLane13 = + /* */ + 524288; + var TransitionLane14 = + /* */ + 1048576; + var TransitionLane15 = + /* */ + 2097152; + var RetryLanes = + /* */ + 62914560; + var RetryLane1 = + /* */ + 4194304; + var RetryLane2 = + /* */ + 8388608; + var RetryLane3 = + /* */ + 16777216; + var RetryLane4 = + /* */ + 33554432; + var SomeRetryLane = RetryLane1; + var SelectiveHydrationLane = + /* */ + 67108864; + var NonIdleLanes = + /* */ + 134217727; + var IdleHydrationLane = + /* */ + 134217728; + var IdleLane = + /* */ + 268435456; + var OffscreenLane = + /* */ + 536870912; + var DeferredLane = + /* */ + 1073741824; // Any lane that might schedule an update. This is used to detect infinite + // update loops, so it doesn't include hydration lanes or retries. + + var UpdateLanes = + SyncLane | InputContinuousLane | DefaultLane | TransitionLanes; // This function is used for the experimental timeline (react-devtools-timeline) + // It should be kept in sync with the Lanes values above. + + function getLabelForLane(lane) { + if (enableSchedulingProfiler) { + if (lane & SyncHydrationLane) { + return "SyncHydrationLane"; + } + + if (lane & SyncLane) { + return "Sync"; + } + + if (lane & InputContinuousHydrationLane) { + return "InputContinuousHydration"; + } + + if (lane & InputContinuousLane) { + return "InputContinuous"; + } + + if (lane & DefaultHydrationLane) { + return "DefaultHydration"; + } + + if (lane & DefaultLane) { + return "Default"; + } + + if (lane & TransitionHydrationLane) { + return "TransitionHydration"; + } + + if (lane & TransitionLanes) { + return "Transition"; + } -var NoMode = - /* */ - 0; // TODO: Remove ConcurrentMode by reading from the root tag instead - -var ConcurrentMode = - /* */ - 1; -var ProfileMode = - /* */ - 2; -var DebugTracingMode = - /* */ - 4; -var StrictLegacyMode = - /* */ - 8; -var StrictEffectsMode = - /* */ - 16; -var ConcurrentUpdatesByDefaultMode = - /* */ - 32; -var NoStrictPassiveEffectsMode = - /* */ - 64; - -// TODO: This is pretty well supported by browsers. Maybe we can drop it. -var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; // Count leading zeros. -// Based on: -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 - -var log$1 = Math.log; -var LN2 = Math.LN2; - -function clz32Fallback(x) { - var asUint = x >>> 0; - - if (asUint === 0) { - return 32; - } - - return (31 - ((log$1(asUint) / LN2) | 0)) | 0; -} + if (lane & RetryLanes) { + return "Retry"; + } -// If those values are changed that package should be rebuilt and redeployed. - -var TotalLanes = 31; -var NoLanes = - /* */ - 0; -var NoLane = - /* */ - 0; -var SyncHydrationLane = - /* */ - 1; -var SyncLane = - /* */ - 2; -var SyncLaneIndex = 1; -var InputContinuousHydrationLane = - /* */ - 4; -var InputContinuousLane = - /* */ - 8; -var DefaultHydrationLane = - /* */ - 16; -var DefaultLane = - /* */ - 32; -var SyncUpdateLanes = enableUnifiedSyncLane - ? SyncLane | InputContinuousLane | DefaultLane - : SyncLane; -var TransitionHydrationLane = - /* */ - 64; -var TransitionLanes = - /* */ - 4194176; -var TransitionLane1 = - /* */ - 128; -var TransitionLane2 = - /* */ - 256; -var TransitionLane3 = - /* */ - 512; -var TransitionLane4 = - /* */ - 1024; -var TransitionLane5 = - /* */ - 2048; -var TransitionLane6 = - /* */ - 4096; -var TransitionLane7 = - /* */ - 8192; -var TransitionLane8 = - /* */ - 16384; -var TransitionLane9 = - /* */ - 32768; -var TransitionLane10 = - /* */ - 65536; -var TransitionLane11 = - /* */ - 131072; -var TransitionLane12 = - /* */ - 262144; -var TransitionLane13 = - /* */ - 524288; -var TransitionLane14 = - /* */ - 1048576; -var TransitionLane15 = - /* */ - 2097152; -var RetryLanes = - /* */ - 62914560; -var RetryLane1 = - /* */ - 4194304; -var RetryLane2 = - /* */ - 8388608; -var RetryLane3 = - /* */ - 16777216; -var RetryLane4 = - /* */ - 33554432; -var SomeRetryLane = RetryLane1; -var SelectiveHydrationLane = - /* */ - 67108864; -var NonIdleLanes = - /* */ - 134217727; -var IdleHydrationLane = - /* */ - 134217728; -var IdleLane = - /* */ - 268435456; -var OffscreenLane = - /* */ - 536870912; -var DeferredLane = - /* */ - 1073741824; // Any lane that might schedule an update. This is used to detect infinite -// update loops, so it doesn't include hydration lanes or retries. - -var UpdateLanes = - SyncLane | InputContinuousLane | DefaultLane | TransitionLanes; // This function is used for the experimental timeline (react-devtools-timeline) -// It should be kept in sync with the Lanes values above. - -function getLabelForLane(lane) { - if (enableSchedulingProfiler) { - if (lane & SyncHydrationLane) { - return "SyncHydrationLane"; - } - - if (lane & SyncLane) { - return "Sync"; - } - - if (lane & InputContinuousHydrationLane) { - return "InputContinuousHydration"; - } - - if (lane & InputContinuousLane) { - return "InputContinuous"; - } - - if (lane & DefaultHydrationLane) { - return "DefaultHydration"; - } - - if (lane & DefaultLane) { - return "Default"; - } - - if (lane & TransitionHydrationLane) { - return "TransitionHydration"; - } - - if (lane & TransitionLanes) { - return "Transition"; - } - - if (lane & RetryLanes) { - return "Retry"; - } - - if (lane & SelectiveHydrationLane) { - return "SelectiveHydration"; - } + if (lane & SelectiveHydrationLane) { + return "SelectiveHydration"; + } - if (lane & IdleHydrationLane) { - return "IdleHydration"; - } + if (lane & IdleHydrationLane) { + return "IdleHydration"; + } - if (lane & IdleLane) { - return "Idle"; - } + if (lane & IdleLane) { + return "Idle"; + } - if (lane & OffscreenLane) { - return "Offscreen"; - } + if (lane & OffscreenLane) { + return "Offscreen"; + } - if (lane & DeferredLane) { - return "Deferred"; + if (lane & DeferredLane) { + return "Deferred"; + } + } } - } -} -var NoTimestamp = -1; -var nextTransitionLane = TransitionLane1; -var nextRetryLane = RetryLane1; - -function getHighestPriorityLanes(lanes) { - if (enableUnifiedSyncLane) { - var pendingSyncLanes = lanes & SyncUpdateLanes; - - if (pendingSyncLanes !== 0) { - return pendingSyncLanes; - } - } - - switch (getHighestPriorityLane(lanes)) { - case SyncHydrationLane: - return SyncHydrationLane; - - case SyncLane: - return SyncLane; - - case InputContinuousHydrationLane: - return InputContinuousHydrationLane; - - case InputContinuousLane: - return InputContinuousLane; - - case DefaultHydrationLane: - return DefaultHydrationLane; - - case DefaultLane: - return DefaultLane; - - case TransitionHydrationLane: - return TransitionHydrationLane; - - case TransitionLane1: - case TransitionLane2: - case TransitionLane3: - case TransitionLane4: - case TransitionLane5: - case TransitionLane6: - case TransitionLane7: - case TransitionLane8: - case TransitionLane9: - case TransitionLane10: - case TransitionLane11: - case TransitionLane12: - case TransitionLane13: - case TransitionLane14: - case TransitionLane15: - return lanes & TransitionLanes; - - case RetryLane1: - case RetryLane2: - case RetryLane3: - case RetryLane4: - return lanes & RetryLanes; - - case SelectiveHydrationLane: - return SelectiveHydrationLane; - - case IdleHydrationLane: - return IdleHydrationLane; - - case IdleLane: - return IdleLane; - - case OffscreenLane: - return OffscreenLane; - - case DeferredLane: - // This shouldn't be reachable because deferred work is always entangled - // with something else. - return NoLanes; + var NoTimestamp = -1; + var nextTransitionLane = TransitionLane1; + var nextRetryLane = RetryLane1; - default: - { - error("Should have found matching lanes. This is a bug in React."); - } // This shouldn't be reachable, but as a fallback, return the entire bitmask. + function getHighestPriorityLanes(lanes) { + if (enableUnifiedSyncLane) { + var pendingSyncLanes = lanes & SyncUpdateLanes; - return lanes; - } -} + if (pendingSyncLanes !== 0) { + return pendingSyncLanes; + } + } -function getNextLanes(root, wipLanes) { - // Early bailout if there's no pending work left. - var pendingLanes = root.pendingLanes; + switch (getHighestPriorityLane(lanes)) { + case SyncHydrationLane: + return SyncHydrationLane; - if (pendingLanes === NoLanes) { - return NoLanes; - } + case SyncLane: + return SyncLane; - var nextLanes = NoLanes; - var suspendedLanes = root.suspendedLanes; - var pingedLanes = root.pingedLanes; // Do not work on any idle work until all the non-idle work has finished, - // even if the work is suspended. + case InputContinuousHydrationLane: + return InputContinuousHydrationLane; - var nonIdlePendingLanes = pendingLanes & NonIdleLanes; + case InputContinuousLane: + return InputContinuousLane; - if (nonIdlePendingLanes !== NoLanes) { - var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; + case DefaultHydrationLane: + return DefaultHydrationLane; - if (nonIdleUnblockedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); - } else { - var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; + case DefaultLane: + return DefaultLane; - if (nonIdlePingedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); - } - } - } else { - // The only remaining work is Idle. - var unblockedLanes = pendingLanes & ~suspendedLanes; + case TransitionHydrationLane: + return TransitionHydrationLane; - if (unblockedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(unblockedLanes); - } else { - if (pingedLanes !== NoLanes) { - nextLanes = getHighestPriorityLanes(pingedLanes); - } - } - } + case TransitionLane1: + case TransitionLane2: + case TransitionLane3: + case TransitionLane4: + case TransitionLane5: + case TransitionLane6: + case TransitionLane7: + case TransitionLane8: + case TransitionLane9: + case TransitionLane10: + case TransitionLane11: + case TransitionLane12: + case TransitionLane13: + case TransitionLane14: + case TransitionLane15: + return lanes & TransitionLanes; - if (nextLanes === NoLanes) { - // This should only be reachable if we're suspended - // TODO: Consider warning in this path if a fallback timer is not scheduled. - return NoLanes; - } // If we're already in the middle of a render, switching lanes will interrupt - // it and we'll lose our progress. We should only do this if the new lanes are - // higher priority. + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + return lanes & RetryLanes; - if ( - wipLanes !== NoLanes && - wipLanes !== nextLanes && // If we already suspended with a delay, then interrupting is fine. Don't - // bother waiting until the root is complete. - (wipLanes & suspendedLanes) === NoLanes - ) { - var nextLane = getHighestPriorityLane(nextLanes); - var wipLane = getHighestPriorityLane(wipLanes); + case SelectiveHydrationLane: + return SelectiveHydrationLane; - if ( - // Tests whether the next lane is equal or lower priority than the wip - // one. This works because the bits decrease in priority as you go left. - nextLane >= wipLane || // Default priority updates should not interrupt transition updates. The - // only difference between default updates and transition updates is that - // default updates do not support refresh transitions. - (nextLane === DefaultLane && (wipLane & TransitionLanes) !== NoLanes) - ) { - // Keep working on the existing in-progress tree. Do not interrupt. - return wipLanes; - } - } + case IdleHydrationLane: + return IdleHydrationLane; - return nextLanes; -} -function getEntangledLanes(root, renderLanes) { - var entangledLanes = renderLanes; - - if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode); - else if ((entangledLanes & InputContinuousLane) !== NoLanes) { - // When updates are sync by default, we entangle continuous priority updates - // and default updates, so they render in the same batch. The only reason - // they use separate lanes is because continuous updates should interrupt - // transitions, but default updates should not. - entangledLanes |= entangledLanes & DefaultLane; - } // Check for entangled lanes and add them to the batch. - // - // A lane is said to be entangled with another when it's not allowed to render - // in a batch that does not also include the other lane. Typically we do this - // when multiple updates have the same source, and we only want to respond to - // the most recent event from that source. - // - // Note that we apply entanglements *after* checking for partial work above. - // This means that if a lane is entangled during an interleaved event while - // it's already rendering, we won't interrupt it. This is intentional, since - // entanglement is usually "best effort": we'll try our best to render the - // lanes in the same batch, but it's not worth throwing out partially - // completed work in order to do it. - // TODO: Reconsider this. The counter-argument is that the partial work - // represents an intermediate state, which we don't want to show to the user. - // And by spending extra time finishing it, we're increasing the amount of - // time it takes to show the final state, which is what they are actually - // waiting for. - // - // For those exceptions where entanglement is semantically important, - // we should ensure that there is no partial work at the - // time we apply the entanglement. - - var allEntangledLanes = root.entangledLanes; - - if (allEntangledLanes !== NoLanes) { - var entanglements = root.entanglements; - var lanes = entangledLanes & allEntangledLanes; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - entangledLanes |= entanglements[index]; - lanes &= ~lane; - } - } - - return entangledLanes; -} + case IdleLane: + return IdleLane; -function computeExpirationTime(lane, currentTime) { - switch (lane) { - case SyncHydrationLane: - case SyncLane: - case InputContinuousHydrationLane: - case InputContinuousLane: - // User interactions should expire slightly more quickly. - // - // NOTE: This is set to the corresponding constant as in Scheduler.js. - // When we made it larger, a product metric in www regressed, suggesting - // there's a user interaction that's being starved by a series of - // synchronous updates. If that theory is correct, the proper solution is - // to fix the starvation. However, this scenario supports the idea that - // expiration times are an important safeguard when starvation - // does happen. - return currentTime + 250; - - case DefaultHydrationLane: - case DefaultLane: - case TransitionHydrationLane: - case TransitionLane1: - case TransitionLane2: - case TransitionLane3: - case TransitionLane4: - case TransitionLane5: - case TransitionLane6: - case TransitionLane7: - case TransitionLane8: - case TransitionLane9: - case TransitionLane10: - case TransitionLane11: - case TransitionLane12: - case TransitionLane13: - case TransitionLane14: - case TransitionLane15: - return currentTime + 5000; - - case RetryLane1: - case RetryLane2: - case RetryLane3: - case RetryLane4: - // TODO: Retries should be allowed to expire if they are CPU bound for - // too long, but when I made this change it caused a spike in browser - // crashes. There must be some other underlying bug; not super urgent but - // ideally should figure out why and fix it. Unfortunately we don't have - // a repro for the crashes, only detected via production metrics. - return NoTimestamp; - - case SelectiveHydrationLane: - case IdleHydrationLane: - case IdleLane: - case OffscreenLane: - case DeferredLane: - // Anything idle priority or lower should never expire. - return NoTimestamp; - - default: - { - error("Should have found matching lanes. This is a bug in React."); - } - - return NoTimestamp; - } -} + case OffscreenLane: + return OffscreenLane; -function markStarvedLanesAsExpired(root, currentTime) { - // TODO: This gets called every time we yield. We can optimize by storing - // the earliest expiration time on the root. Then use that to quickly bail out - // of this function. - var pendingLanes = root.pendingLanes; - var suspendedLanes = root.suspendedLanes; - var pingedLanes = root.pingedLanes; - var expirationTimes = root.expirationTimes; // Iterate through the pending lanes and check if we've reached their - // expiration time. If so, we'll assume the update is being starved and mark - // it as expired to force it to finish. - // TODO: We should be able to replace this with upgradePendingLanesToSync - // - // We exclude retry lanes because those must always be time sliced, in order - // to unwrap uncached promises. - // TODO: Write a test for this - - var lanes = pendingLanes & ~RetryLanes; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - var expirationTime = expirationTimes[index]; - - if (expirationTime === NoTimestamp) { - // Found a pending lane with no expiration time. If it's not suspended, or - // if it's pinged, assume it's CPU-bound. Compute a new expiration time - // using the current time. - if ( - (lane & suspendedLanes) === NoLanes || - (lane & pingedLanes) !== NoLanes - ) { - // Assumes timestamps are monotonically increasing. - expirationTimes[index] = computeExpirationTime(lane, currentTime); + case DeferredLane: + // This shouldn't be reachable because deferred work is always entangled + // with something else. + return NoLanes; + + default: + { + error("Should have found matching lanes. This is a bug in React."); + } // This shouldn't be reachable, but as a fallback, return the entire bitmask. + + return lanes; } - } else if (expirationTime <= currentTime) { - // This lane expired - root.expiredLanes |= lane; } - lanes &= ~lane; - } -} // This returns the highest priority pending lanes regardless of whether they -// are suspended. + function getNextLanes(root, wipLanes) { + // Early bailout if there's no pending work left. + var pendingLanes = root.pendingLanes; -function getHighestPriorityPendingLanes(root) { - return getHighestPriorityLanes(root.pendingLanes); -} -function getLanesToRetrySynchronouslyOnError(root, originallyAttemptedLanes) { - if (root.errorRecoveryDisabledLanes & originallyAttemptedLanes) { - // The error recovery mechanism is disabled until these lanes are cleared. - return NoLanes; - } + if (pendingLanes === NoLanes) { + return NoLanes; + } - var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; + var nextLanes = NoLanes; + var suspendedLanes = root.suspendedLanes; + var pingedLanes = root.pingedLanes; // Do not work on any idle work until all the non-idle work has finished, + // even if the work is suspended. - if (everythingButOffscreen !== NoLanes) { - return everythingButOffscreen; - } + var nonIdlePendingLanes = pendingLanes & NonIdleLanes; - if (everythingButOffscreen & OffscreenLane) { - return OffscreenLane; - } + if (nonIdlePendingLanes !== NoLanes) { + var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; - return NoLanes; -} -function includesSyncLane(lanes) { - return (lanes & (SyncLane | SyncHydrationLane)) !== NoLanes; -} -function includesNonIdleWork(lanes) { - return (lanes & NonIdleLanes) !== NoLanes; -} -function includesOnlyRetries(lanes) { - return (lanes & RetryLanes) === lanes; -} -function includesOnlyNonUrgentLanes(lanes) { - // TODO: Should hydration lanes be included here? This function is only - // used in `updateDeferredValueImpl`. - var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; - return (lanes & UrgentLanes) === NoLanes; -} -function includesOnlyTransitions(lanes) { - return (lanes & TransitionLanes) === lanes; -} -function includesBlockingLane(root, lanes) { - if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode) { - // Concurrent updates by default always use time slicing. - return false; - } - - var SyncDefaultLanes = - InputContinuousHydrationLane | - InputContinuousLane | - DefaultHydrationLane | - DefaultLane; - return (lanes & SyncDefaultLanes) !== NoLanes; -} -function includesExpiredLane(root, lanes) { - // This is a separate check from includesBlockingLane because a lane can - // expire after a render has already started. - return (lanes & root.expiredLanes) !== NoLanes; -} -function isTransitionLane(lane) { - return (lane & TransitionLanes) !== NoLanes; -} -function claimNextTransitionLane() { - // Cycle through the lanes, assigning each new transition to the next lane. - // In most cases, this means every transition gets its own lane, until we - // run out of lanes and cycle back to the beginning. - var lane = nextTransitionLane; - nextTransitionLane <<= 1; - - if ((nextTransitionLane & TransitionLanes) === NoLanes) { - nextTransitionLane = TransitionLane1; - } - - return lane; -} -function claimNextRetryLane() { - var lane = nextRetryLane; - nextRetryLane <<= 1; + if (nonIdleUnblockedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); + } else { + var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; - if ((nextRetryLane & RetryLanes) === NoLanes) { - nextRetryLane = RetryLane1; - } + if (nonIdlePingedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); + } + } + } else { + // The only remaining work is Idle. + var unblockedLanes = pendingLanes & ~suspendedLanes; - return lane; -} -function getHighestPriorityLane(lanes) { - return lanes & -lanes; -} -function pickArbitraryLane(lanes) { - // This wrapper function gets inlined. Only exists so to communicate that it - // doesn't matter which bit is selected; you can pick any bit without - // affecting the algorithms where its used. Here I'm using - // getHighestPriorityLane because it requires the fewest operations. - return getHighestPriorityLane(lanes); -} + if (unblockedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(unblockedLanes); + } else { + if (pingedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(pingedLanes); + } + } + } -function pickArbitraryLaneIndex(lanes) { - return 31 - clz32(lanes); -} + if (nextLanes === NoLanes) { + // This should only be reachable if we're suspended + // TODO: Consider warning in this path if a fallback timer is not scheduled. + return NoLanes; + } // If we're already in the middle of a render, switching lanes will interrupt + // it and we'll lose our progress. We should only do this if the new lanes are + // higher priority. -function laneToIndex(lane) { - return pickArbitraryLaneIndex(lane); -} + if ( + wipLanes !== NoLanes && + wipLanes !== nextLanes && // If we already suspended with a delay, then interrupting is fine. Don't + // bother waiting until the root is complete. + (wipLanes & suspendedLanes) === NoLanes + ) { + var nextLane = getHighestPriorityLane(nextLanes); + var wipLane = getHighestPriorityLane(wipLanes); -function includesSomeLane(a, b) { - return (a & b) !== NoLanes; -} -function isSubsetOfLanes(set, subset) { - return (set & subset) === subset; -} -function mergeLanes(a, b) { - return a | b; -} -function removeLanes(set, subset) { - return set & ~subset; -} -function intersectLanes(a, b) { - return a & b; -} // Seems redundant, but it changes the type from a single lane (used for -// updates) to a group of lanes (used for flushing work). + if ( + // Tests whether the next lane is equal or lower priority than the wip + // one. This works because the bits decrease in priority as you go left. + nextLane >= wipLane || // Default priority updates should not interrupt transition updates. The + // only difference between default updates and transition updates is that + // default updates do not support refresh transitions. + (nextLane === DefaultLane && (wipLane & TransitionLanes) !== NoLanes) + ) { + // Keep working on the existing in-progress tree. Do not interrupt. + return wipLanes; + } + } -function laneToLanes(lane) { - return lane; -} -function higherPriorityLane(a, b) { - // This works because the bit ranges decrease in priority as you go left. - return a !== NoLane && a < b ? a : b; -} -function createLaneMap(initial) { - // Intentionally pushing one by one. - // https://v8.dev/blog/elements-kinds#avoid-creating-holes - var laneMap = []; + return nextLanes; + } + function getEntangledLanes(root, renderLanes) { + var entangledLanes = renderLanes; - for (var i = 0; i < TotalLanes; i++) { - laneMap.push(initial); - } + if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode); + else if ((entangledLanes & InputContinuousLane) !== NoLanes) { + // When updates are sync by default, we entangle continuous priority updates + // and default updates, so they render in the same batch. The only reason + // they use separate lanes is because continuous updates should interrupt + // transitions, but default updates should not. + entangledLanes |= entangledLanes & DefaultLane; + } // Check for entangled lanes and add them to the batch. + // + // A lane is said to be entangled with another when it's not allowed to render + // in a batch that does not also include the other lane. Typically we do this + // when multiple updates have the same source, and we only want to respond to + // the most recent event from that source. + // + // Note that we apply entanglements *after* checking for partial work above. + // This means that if a lane is entangled during an interleaved event while + // it's already rendering, we won't interrupt it. This is intentional, since + // entanglement is usually "best effort": we'll try our best to render the + // lanes in the same batch, but it's not worth throwing out partially + // completed work in order to do it. + // TODO: Reconsider this. The counter-argument is that the partial work + // represents an intermediate state, which we don't want to show to the user. + // And by spending extra time finishing it, we're increasing the amount of + // time it takes to show the final state, which is what they are actually + // waiting for. + // + // For those exceptions where entanglement is semantically important, + // we should ensure that there is no partial work at the + // time we apply the entanglement. - return laneMap; -} -function markRootUpdated(root, updateLane) { - root.pendingLanes |= updateLane; // If there are any suspended transitions, it's possible this new update - // could unblock them. Clear the suspended lanes so that we can try rendering - // them again. - // - // TODO: We really only need to unsuspend only lanes that are in the - // `subtreeLanes` of the updated fiber, or the update lanes of the return - // path. This would exclude suspended updates in an unrelated sibling tree, - // since there's no way for this update to unblock it. - // - // We don't do this if the incoming update is idle, because we never process - // idle updates until after all the regular updates have finished; there's no - // way it could unblock a transition. - - if (updateLane !== IdleLane) { - root.suspendedLanes = NoLanes; - root.pingedLanes = NoLanes; - } -} -function markRootSuspended$1(root, suspendedLanes, spawnedLane) { - root.suspendedLanes |= suspendedLanes; - root.pingedLanes &= ~suspendedLanes; // The suspended lanes are no longer CPU-bound. Clear their expiration times. - - var expirationTimes = root.expirationTimes; - var lanes = suspendedLanes; - - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - expirationTimes[index] = NoTimestamp; - lanes &= ~lane; - } - - if (spawnedLane !== NoLane) { - markSpawnedDeferredLane(root, spawnedLane, suspendedLanes); - } -} -function markRootPinged(root, pingedLanes) { - root.pingedLanes |= root.suspendedLanes & pingedLanes; -} -function markRootFinished(root, remainingLanes, spawnedLane) { - var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; - root.pendingLanes = remainingLanes; // Let's try everything again + var allEntangledLanes = root.entangledLanes; - root.suspendedLanes = NoLanes; - root.pingedLanes = NoLanes; - root.expiredLanes &= remainingLanes; - root.entangledLanes &= remainingLanes; - root.errorRecoveryDisabledLanes &= remainingLanes; - root.shellSuspendCounter = 0; - var entanglements = root.entanglements; - var expirationTimes = root.expirationTimes; - var hiddenUpdates = root.hiddenUpdates; // Clear the lanes that no longer have pending work + if (allEntangledLanes !== NoLanes) { + var entanglements = root.entanglements; + var lanes = entangledLanes & allEntangledLanes; - var lanes = noLongerPendingLanes; + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + entangledLanes |= entanglements[index]; + lanes &= ~lane; + } + } - while (lanes > 0) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - entanglements[index] = NoLanes; - expirationTimes[index] = NoTimestamp; - var hiddenUpdatesForLane = hiddenUpdates[index]; + return entangledLanes; + } - if (hiddenUpdatesForLane !== null) { - hiddenUpdates[index] = null; // "Hidden" updates are updates that were made to a hidden component. They - // have special logic associated with them because they may be entangled - // with updates that occur outside that tree. But once the outer tree - // commits, they behave like regular updates. + function computeExpirationTime(lane, currentTime) { + switch (lane) { + case SyncHydrationLane: + case SyncLane: + case InputContinuousHydrationLane: + case InputContinuousLane: + // User interactions should expire slightly more quickly. + // + // NOTE: This is set to the corresponding constant as in Scheduler.js. + // When we made it larger, a product metric in www regressed, suggesting + // there's a user interaction that's being starved by a series of + // synchronous updates. If that theory is correct, the proper solution is + // to fix the starvation. However, this scenario supports the idea that + // expiration times are an important safeguard when starvation + // does happen. + return currentTime + 250; + + case DefaultHydrationLane: + case DefaultLane: + case TransitionHydrationLane: + case TransitionLane1: + case TransitionLane2: + case TransitionLane3: + case TransitionLane4: + case TransitionLane5: + case TransitionLane6: + case TransitionLane7: + case TransitionLane8: + case TransitionLane9: + case TransitionLane10: + case TransitionLane11: + case TransitionLane12: + case TransitionLane13: + case TransitionLane14: + case TransitionLane15: + return currentTime + 5000; + + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + // TODO: Retries should be allowed to expire if they are CPU bound for + // too long, but when I made this change it caused a spike in browser + // crashes. There must be some other underlying bug; not super urgent but + // ideally should figure out why and fix it. Unfortunately we don't have + // a repro for the crashes, only detected via production metrics. + return NoTimestamp; + + case SelectiveHydrationLane: + case IdleHydrationLane: + case IdleLane: + case OffscreenLane: + case DeferredLane: + // Anything idle priority or lower should never expire. + return NoTimestamp; - for (var i = 0; i < hiddenUpdatesForLane.length; i++) { - var update = hiddenUpdatesForLane[i]; + default: + { + error("Should have found matching lanes. This is a bug in React."); + } - if (update !== null) { - update.lane &= ~OffscreenLane; - } + return NoTimestamp; } } - lanes &= ~lane; - } + function markStarvedLanesAsExpired(root, currentTime) { + // TODO: This gets called every time we yield. We can optimize by storing + // the earliest expiration time on the root. Then use that to quickly bail out + // of this function. + var pendingLanes = root.pendingLanes; + var suspendedLanes = root.suspendedLanes; + var pingedLanes = root.pingedLanes; + var expirationTimes = root.expirationTimes; // Iterate through the pending lanes and check if we've reached their + // expiration time. If so, we'll assume the update is being starved and mark + // it as expired to force it to finish. + // TODO: We should be able to replace this with upgradePendingLanesToSync + // + // We exclude retry lanes because those must always be time sliced, in order + // to unwrap uncached promises. + // TODO: Write a test for this - if (spawnedLane !== NoLane) { - markSpawnedDeferredLane( - root, - spawnedLane, // This render finished successfully without suspending, so we don't need - // to entangle the spawned task with the parent task. - NoLanes - ); - } -} + var lanes = pendingLanes & ~RetryLanes; -function markSpawnedDeferredLane(root, spawnedLane, entangledLanes) { - // This render spawned a deferred task. Mark it as pending. - root.pendingLanes |= spawnedLane; - root.suspendedLanes &= ~spawnedLane; // Entangle the spawned lane with the DeferredLane bit so that we know it - // was the result of another render. This lets us avoid a useDeferredValue - // waterfall — only the first level will defer. - - var spawnedLaneIndex = laneToIndex(spawnedLane); - root.entangledLanes |= spawnedLane; - root.entanglements[spawnedLaneIndex] |= - DeferredLane | // If the parent render task suspended, we must also entangle those lanes - // with the spawned task, so that the deferred task includes all the same - // updates that the parent task did. We can exclude any lane that is not - // used for updates (e.g. Offscreen). - (entangledLanes & UpdateLanes); -} + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + var expirationTime = expirationTimes[index]; -function markRootEntangled(root, entangledLanes) { - // In addition to entangling each of the given lanes with each other, we also - // have to consider _transitive_ entanglements. For each lane that is already - // entangled with *any* of the given lanes, that lane is now transitively - // entangled with *all* the given lanes. - // - // Translated: If C is entangled with A, then entangling A with B also - // entangles C with B. - // - // If this is hard to grasp, it might help to intentionally break this - // function and look at the tests that fail in ReactTransition-test.js. Try - // commenting out one of the conditions below. - var rootEntangledLanes = (root.entangledLanes |= entangledLanes); - var entanglements = root.entanglements; - var lanes = rootEntangledLanes; - - while (lanes) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; + if (expirationTime === NoTimestamp) { + // Found a pending lane with no expiration time. If it's not suspended, or + // if it's pinged, assume it's CPU-bound. Compute a new expiration time + // using the current time. + if ( + (lane & suspendedLanes) === NoLanes || + (lane & pingedLanes) !== NoLanes + ) { + // Assumes timestamps are monotonically increasing. + expirationTimes[index] = computeExpirationTime(lane, currentTime); + } + } else if (expirationTime <= currentTime) { + // This lane expired + root.expiredLanes |= lane; + } - if ( - // Is this one of the newly entangled lanes? - (lane & entangledLanes) | // Is this lane transitively entangled with the newly entangled lanes? - (entanglements[index] & entangledLanes) - ) { - entanglements[index] |= entangledLanes; + lanes &= ~lane; + } + } // This returns the highest priority pending lanes regardless of whether they + // are suspended. + + function getHighestPriorityPendingLanes(root) { + return getHighestPriorityLanes(root.pendingLanes); } + function getLanesToRetrySynchronouslyOnError( + root, + originallyAttemptedLanes + ) { + if (root.errorRecoveryDisabledLanes & originallyAttemptedLanes) { + // The error recovery mechanism is disabled until these lanes are cleared. + return NoLanes; + } - lanes &= ~lane; - } -} -function upgradePendingLaneToSync(root, lane) { - // Since we're upgrading the priority of the given lane, there is now pending - // sync work. - root.pendingLanes |= SyncLane; // Entangle the sync lane with the lane we're upgrading. This means SyncLane - // will not be allowed to finish without also finishing the given lane. - - root.entangledLanes |= SyncLane; - root.entanglements[SyncLaneIndex] |= lane; -} -function upgradePendingLanesToSync(root, lanesToUpgrade) { - // Same as upgradePendingLaneToSync but accepts multiple lanes, so it's a - // bit slower. - root.pendingLanes |= SyncLane; - root.entangledLanes |= SyncLane; - var lanes = lanesToUpgrade; - - while (lanes) { - var index = pickArbitraryLaneIndex(lanes); - var lane = 1 << index; - root.entanglements[SyncLaneIndex] |= lane; - lanes &= ~lane; - } -} -function markHiddenUpdate(root, update, lane) { - var index = laneToIndex(lane); - var hiddenUpdates = root.hiddenUpdates; - var hiddenUpdatesForLane = hiddenUpdates[index]; - - if (hiddenUpdatesForLane === null) { - hiddenUpdates[index] = [update]; - } else { - hiddenUpdatesForLane.push(update); - } - - update.lane = lane | OffscreenLane; -} -function getBumpedLaneForHydration(root, renderLanes) { - var renderLane = getHighestPriorityLane(renderLanes); - var lane; - - if (enableUnifiedSyncLane && (renderLane & SyncUpdateLanes) !== NoLane) { - lane = SyncHydrationLane; - } else { - switch (renderLane) { - case SyncLane: - lane = SyncHydrationLane; - break; - - case InputContinuousLane: - lane = InputContinuousHydrationLane; - break; - - case DefaultLane: - lane = DefaultHydrationLane; - break; - - case TransitionLane1: - case TransitionLane2: - case TransitionLane3: - case TransitionLane4: - case TransitionLane5: - case TransitionLane6: - case TransitionLane7: - case TransitionLane8: - case TransitionLane9: - case TransitionLane10: - case TransitionLane11: - case TransitionLane12: - case TransitionLane13: - case TransitionLane14: - case TransitionLane15: - case RetryLane1: - case RetryLane2: - case RetryLane3: - case RetryLane4: - lane = TransitionHydrationLane; - break; - - case IdleLane: - lane = IdleHydrationLane; - break; - - default: - // Everything else is already either a hydration lane, or shouldn't - // be retried at a hydration lane. - lane = NoLane; - break; - } - } // Check if the lane we chose is suspended. If so, that indicates that we - // already attempted and failed to hydrate at that level. Also check if we're - // already rendering that lane, which is rare but could happen. - - if ((lane & (root.suspendedLanes | renderLanes)) !== NoLane) { - // Give up trying to hydrate and fall back to client render. - return NoLane; - } - - return lane; -} -function addFiberToLanesMap(root, fiber, lanes) { - if (!isDevToolsPresent) { - return; - } - - var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; - - while (lanes > 0) { - var index = laneToIndex(lanes); - var lane = 1 << index; - var updaters = pendingUpdatersLaneMap[index]; - updaters.add(fiber); - lanes &= ~lane; - } -} -function movePendingFibersToMemoized(root, lanes) { - if (!isDevToolsPresent) { - return; - } + var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; - var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; - var memoizedUpdaters = root.memoizedUpdaters; + if (everythingButOffscreen !== NoLanes) { + return everythingButOffscreen; + } - while (lanes > 0) { - var index = laneToIndex(lanes); - var lane = 1 << index; - var updaters = pendingUpdatersLaneMap[index]; + if (everythingButOffscreen & OffscreenLane) { + return OffscreenLane; + } - if (updaters.size > 0) { - updaters.forEach(function (fiber) { - var alternate = fiber.alternate; + return NoLanes; + } + function includesSyncLane(lanes) { + return (lanes & (SyncLane | SyncHydrationLane)) !== NoLanes; + } + function includesNonIdleWork(lanes) { + return (lanes & NonIdleLanes) !== NoLanes; + } + function includesOnlyRetries(lanes) { + return (lanes & RetryLanes) === lanes; + } + function includesOnlyNonUrgentLanes(lanes) { + // TODO: Should hydration lanes be included here? This function is only + // used in `updateDeferredValueImpl`. + var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; + return (lanes & UrgentLanes) === NoLanes; + } + function includesOnlyTransitions(lanes) { + return (lanes & TransitionLanes) === lanes; + } + function includesBlockingLane(root, lanes) { + if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode) { + // Concurrent updates by default always use time slicing. + return false; + } - if (alternate === null || !memoizedUpdaters.has(alternate)) { - memoizedUpdaters.add(fiber); - } - }); - updaters.clear(); + var SyncDefaultLanes = + InputContinuousHydrationLane | + InputContinuousLane | + DefaultHydrationLane | + DefaultLane; + return (lanes & SyncDefaultLanes) !== NoLanes; + } + function includesExpiredLane(root, lanes) { + // This is a separate check from includesBlockingLane because a lane can + // expire after a render has already started. + return (lanes & root.expiredLanes) !== NoLanes; + } + function isTransitionLane(lane) { + return (lane & TransitionLanes) !== NoLanes; } + function claimNextTransitionLane() { + // Cycle through the lanes, assigning each new transition to the next lane. + // In most cases, this means every transition gets its own lane, until we + // run out of lanes and cycle back to the beginning. + var lane = nextTransitionLane; + nextTransitionLane <<= 1; - lanes &= ~lane; - } -} -function addTransitionToLanesMap(root, transition, lane) { - if (enableTransitionTracing) { - var transitionLanesMap = root.transitionLanes; - var index = laneToIndex(lane); - var transitions = transitionLanesMap[index]; + if ((nextTransitionLane & TransitionLanes) === NoLanes) { + nextTransitionLane = TransitionLane1; + } - if (transitions === null) { - transitions = new Set(); + return lane; } + function claimNextRetryLane() { + var lane = nextRetryLane; + nextRetryLane <<= 1; - transitions.add(transition); - transitionLanesMap[index] = transitions; - } -} -function getTransitionsForLanes(root, lanes) { - if (!enableTransitionTracing) { - return null; - } + if ((nextRetryLane & RetryLanes) === NoLanes) { + nextRetryLane = RetryLane1; + } - var transitionsForLanes = []; + return lane; + } + function getHighestPriorityLane(lanes) { + return lanes & -lanes; + } + function pickArbitraryLane(lanes) { + // This wrapper function gets inlined. Only exists so to communicate that it + // doesn't matter which bit is selected; you can pick any bit without + // affecting the algorithms where its used. Here I'm using + // getHighestPriorityLane because it requires the fewest operations. + return getHighestPriorityLane(lanes); + } - while (lanes > 0) { - var index = laneToIndex(lanes); - var lane = 1 << index; - var transitions = root.transitionLanes[index]; + function pickArbitraryLaneIndex(lanes) { + return 31 - clz32(lanes); + } - if (transitions !== null) { - transitions.forEach(function (transition) { - transitionsForLanes.push(transition); - }); + function laneToIndex(lane) { + return pickArbitraryLaneIndex(lane); } - lanes &= ~lane; - } + function includesSomeLane(a, b) { + return (a & b) !== NoLanes; + } + function isSubsetOfLanes(set, subset) { + return (set & subset) === subset; + } + function mergeLanes(a, b) { + return a | b; + } + function removeLanes(set, subset) { + return set & ~subset; + } + function intersectLanes(a, b) { + return a & b; + } // Seems redundant, but it changes the type from a single lane (used for + // updates) to a group of lanes (used for flushing work). - if (transitionsForLanes.length === 0) { - return null; - } + function laneToLanes(lane) { + return lane; + } + function higherPriorityLane(a, b) { + // This works because the bit ranges decrease in priority as you go left. + return a !== NoLane && a < b ? a : b; + } + function createLaneMap(initial) { + // Intentionally pushing one by one. + // https://v8.dev/blog/elements-kinds#avoid-creating-holes + var laneMap = []; - return transitionsForLanes; -} -function clearTransitionsForLanes(root, lanes) { - if (!enableTransitionTracing) { - return; - } + for (var i = 0; i < TotalLanes; i++) { + laneMap.push(initial); + } - while (lanes > 0) { - var index = laneToIndex(lanes); - var lane = 1 << index; - var transitions = root.transitionLanes[index]; + return laneMap; + } + function markRootUpdated(root, updateLane) { + root.pendingLanes |= updateLane; // If there are any suspended transitions, it's possible this new update + // could unblock them. Clear the suspended lanes so that we can try rendering + // them again. + // + // TODO: We really only need to unsuspend only lanes that are in the + // `subtreeLanes` of the updated fiber, or the update lanes of the return + // path. This would exclude suspended updates in an unrelated sibling tree, + // since there's no way for this update to unblock it. + // + // We don't do this if the incoming update is idle, because we never process + // idle updates until after all the regular updates have finished; there's no + // way it could unblock a transition. - if (transitions !== null) { - root.transitionLanes[index] = null; + if (updateLane !== IdleLane) { + root.suspendedLanes = NoLanes; + root.pingedLanes = NoLanes; + } } + function markRootSuspended$1(root, suspendedLanes, spawnedLane) { + root.suspendedLanes |= suspendedLanes; + root.pingedLanes &= ~suspendedLanes; // The suspended lanes are no longer CPU-bound. Clear their expiration times. - lanes &= ~lane; - } -} + var expirationTimes = root.expirationTimes; + var lanes = suspendedLanes; -var DiscreteEventPriority = SyncLane; -var ContinuousEventPriority = InputContinuousLane; -var DefaultEventPriority = DefaultLane; -var IdleEventPriority = IdleLane; -var currentUpdatePriority = NoLane; -function getCurrentUpdatePriority() { - return currentUpdatePriority; -} -function setCurrentUpdatePriority(newPriority) { - currentUpdatePriority = newPriority; -} -function runWithPriority(priority, fn) { - var previousPriority = currentUpdatePriority; - - try { - currentUpdatePriority = priority; - return fn(); - } finally { - currentUpdatePriority = previousPriority; - } -} -function higherEventPriority(a, b) { - return a !== 0 && a < b ? a : b; -} -function lowerEventPriority(a, b) { - return a === 0 || a > b ? a : b; -} -function isHigherEventPriority(a, b) { - return a !== 0 && a < b; -} -function lanesToEventPriority(lanes) { - var lane = getHighestPriorityLane(lanes); + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + expirationTimes[index] = NoTimestamp; + lanes &= ~lane; + } - if (!isHigherEventPriority(DiscreteEventPriority, lane)) { - return DiscreteEventPriority; - } + if (spawnedLane !== NoLane) { + markSpawnedDeferredLane(root, spawnedLane, suspendedLanes); + } + } + function markRootPinged(root, pingedLanes) { + root.pingedLanes |= root.suspendedLanes & pingedLanes; + } + function markRootFinished(root, remainingLanes, spawnedLane) { + var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; + root.pendingLanes = remainingLanes; // Let's try everything again - if (!isHigherEventPriority(ContinuousEventPriority, lane)) { - return ContinuousEventPriority; - } + root.suspendedLanes = NoLanes; + root.pingedLanes = NoLanes; + root.expiredLanes &= remainingLanes; + root.entangledLanes &= remainingLanes; + root.errorRecoveryDisabledLanes &= remainingLanes; + root.shellSuspendCounter = 0; + var entanglements = root.entanglements; + var expirationTimes = root.expirationTimes; + var hiddenUpdates = root.hiddenUpdates; // Clear the lanes that no longer have pending work - if (includesNonIdleWork(lane)) { - return DefaultEventPriority; - } + var lanes = noLongerPendingLanes; - return IdleEventPriority; -} + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + entanglements[index] = NoLanes; + expirationTimes[index] = NoTimestamp; + var hiddenUpdatesForLane = hiddenUpdates[index]; -// $FlowFixMe[method-unbinding] -var hasOwnProperty = Object.prototype.hasOwnProperty; + if (hiddenUpdatesForLane !== null) { + hiddenUpdates[index] = null; // "Hidden" updates are updates that were made to a hidden component. They + // have special logic associated with them because they may be entangled + // with updates that occur outside that tree. But once the outer tree + // commits, they behave like regular updates. -/* - * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol - * and Temporal.* types. See https://github.com/facebook/react/pull/22064. - * - * The functions in this module will throw an easier-to-understand, - * easier-to-debug exception with a clear errors message message explaining the - * problem. (Instead of a confusing exception thrown inside the implementation - * of the `value` object). - */ -// $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. -function typeName(value) { - { - // toStringTag is needed for namespaced types like Temporal.Instant - var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; - var type = - (hasToStringTag && value[Symbol.toStringTag]) || - value.constructor.name || - "Object"; // $FlowFixMe[incompatible-return] - - return type; - } -} // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - -function willCoercionThrow(value) { - { - try { - testStringCoercion(value); - return false; - } catch (e) { - return true; - } - } -} + for (var i = 0; i < hiddenUpdatesForLane.length; i++) { + var update = hiddenUpdatesForLane[i]; -function testStringCoercion(value) { - // If you ended up here by following an exception call stack, here's what's - // happened: you supplied an object or symbol value to React (as a prop, key, - // DOM attribute, CSS property, string ref, etc.) and when React tried to - // coerce it to a string using `'' + value`, an exception was thrown. - // - // The most common types that will cause this exception are `Symbol` instances - // and Temporal objects like `Temporal.Instant`. But any object that has a - // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this - // exception. (Library authors do this to prevent users from using built-in - // numeric operators like `+` or comparison operators like `>=` because custom - // methods are needed to perform accurate arithmetic or comparison.) - // - // To fix the problem, coerce this object or symbol value to a string before - // passing it to React. The most reliable way is usually `String(value)`. - // - // To find which value is throwing, check the browser or debugger console. - // Before this exception was thrown, there should be `console.error` output - // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the - // problem and how that type was used: key, atrribute, input value prop, etc. - // In most cases, this console output also shows the component and its - // ancestor components where the exception happened. - // - // eslint-disable-next-line react-internal/safe-string-coercion - return "" + value; -} + if (update !== null) { + update.lane &= ~OffscreenLane; + } + } + } -function checkAttributeStringCoercion(value, attributeName) { - { - if (willCoercionThrow(value)) { - error( - "The provided `%s` attribute is an unsupported type %s." + - " This value must be coerced to a string before using it here.", - attributeName, - typeName(value) - ); + lanes &= ~lane; + } - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + if (spawnedLane !== NoLane) { + markSpawnedDeferredLane( + root, + spawnedLane, // This render finished successfully without suspending, so we don't need + // to entangle the spawned task with the parent task. + NoLanes + ); + } } - } -} -function checkKeyStringCoercion(value) { - { - if (willCoercionThrow(value)) { - error( - "The provided key is an unsupported type %s." + - " This value must be coerced to a string before using it here.", - typeName(value) - ); - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) - } - } -} -function checkPropStringCoercion(value, propName) { - { - if (willCoercionThrow(value)) { - error( - "The provided `%s` prop is an unsupported type %s." + - " This value must be coerced to a string before using it here.", - propName, - typeName(value) - ); + function markSpawnedDeferredLane(root, spawnedLane, entangledLanes) { + // This render spawned a deferred task. Mark it as pending. + root.pendingLanes |= spawnedLane; + root.suspendedLanes &= ~spawnedLane; // Entangle the spawned lane with the DeferredLane bit so that we know it + // was the result of another render. This lets us avoid a useDeferredValue + // waterfall — only the first level will defer. - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + var spawnedLaneIndex = laneToIndex(spawnedLane); + root.entangledLanes |= spawnedLane; + root.entanglements[spawnedLaneIndex] |= + DeferredLane | // If the parent render task suspended, we must also entangle those lanes + // with the spawned task, so that the deferred task includes all the same + // updates that the parent task did. We can exclude any lane that is not + // used for updates (e.g. Offscreen). + (entangledLanes & UpdateLanes); } - } -} -function checkCSSPropertyStringCoercion(value, propName) { - { - if (willCoercionThrow(value)) { - error( - "The provided `%s` CSS property is an unsupported type %s." + - " This value must be coerced to a string before using it here.", - propName, - typeName(value) - ); - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) - } - } -} -function checkHtmlStringCoercion(value) { - { - if (willCoercionThrow(value)) { - error( - "The provided HTML markup uses a value of unsupported type %s." + - " This value must be coerced to a string before using it here.", - typeName(value) - ); + function markRootEntangled(root, entangledLanes) { + // In addition to entangling each of the given lanes with each other, we also + // have to consider _transitive_ entanglements. For each lane that is already + // entangled with *any* of the given lanes, that lane is now transitively + // entangled with *all* the given lanes. + // + // Translated: If C is entangled with A, then entangling A with B also + // entangles C with B. + // + // If this is hard to grasp, it might help to intentionally break this + // function and look at the tests that fail in ReactTransition-test.js. Try + // commenting out one of the conditions below. + var rootEntangledLanes = (root.entangledLanes |= entangledLanes); + var entanglements = root.entanglements; + var lanes = rootEntangledLanes; - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + while (lanes) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + + if ( + // Is this one of the newly entangled lanes? + (lane & entangledLanes) | // Is this lane transitively entangled with the newly entangled lanes? + (entanglements[index] & entangledLanes) + ) { + entanglements[index] |= entangledLanes; + } + + lanes &= ~lane; + } } - } -} -function checkFormFieldValueStringCoercion(value) { - { - if (willCoercionThrow(value)) { - error( - "Form field values (value, checked, defaultValue, or defaultChecked props)" + - " must be strings, not %s." + - " This value must be coerced to a string before using it here.", - typeName(value) - ); + function upgradePendingLaneToSync(root, lane) { + // Since we're upgrading the priority of the given lane, there is now pending + // sync work. + root.pendingLanes |= SyncLane; // Entangle the sync lane with the lane we're upgrading. This means SyncLane + // will not be allowed to finish without also finishing the given lane. - return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + root.entangledLanes |= SyncLane; + root.entanglements[SyncLaneIndex] |= lane; } - } -} + function upgradePendingLanesToSync(root, lanesToUpgrade) { + // Same as upgradePendingLaneToSync but accepts multiple lanes, so it's a + // bit slower. + root.pendingLanes |= SyncLane; + root.entangledLanes |= SyncLane; + var lanes = lanesToUpgrade; -var allNativeEvents = new Set(); + while (lanes) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + root.entanglements[SyncLaneIndex] |= lane; + lanes &= ~lane; + } + } + function markHiddenUpdate(root, update, lane) { + var index = laneToIndex(lane); + var hiddenUpdates = root.hiddenUpdates; + var hiddenUpdatesForLane = hiddenUpdates[index]; -{ - allNativeEvents.add("beforeblur"); - allNativeEvents.add("afterblur"); -} -/** - * Mapping from registration name to event name - */ + if (hiddenUpdatesForLane === null) { + hiddenUpdates[index] = [update]; + } else { + hiddenUpdatesForLane.push(update); + } -var registrationNameDependencies = {}; -/** - * Mapping from lowercase registration names to the properly cased version, - * used to warn in the case of missing event handlers. Available - * only in __DEV__. - * @type {Object} - */ + update.lane = lane | OffscreenLane; + } + function getBumpedLaneForHydration(root, renderLanes) { + var renderLane = getHighestPriorityLane(renderLanes); + var lane; -var possibleRegistrationNames = {}; // Trust the developer to only use possibleRegistrationNames in true + if (enableUnifiedSyncLane && (renderLane & SyncUpdateLanes) !== NoLane) { + lane = SyncHydrationLane; + } else { + switch (renderLane) { + case SyncLane: + lane = SyncHydrationLane; + break; -function registerTwoPhaseEvent(registrationName, dependencies) { - registerDirectEvent(registrationName, dependencies); - registerDirectEvent(registrationName + "Capture", dependencies); -} -function registerDirectEvent(registrationName, dependencies) { - { - if (registrationNameDependencies[registrationName]) { - error( - "EventRegistry: More than one plugin attempted to publish the same " + - "registration name, `%s`.", - registrationName - ); - } - } + case InputContinuousLane: + lane = InputContinuousHydrationLane; + break; - registrationNameDependencies[registrationName] = dependencies; + case DefaultLane: + lane = DefaultHydrationLane; + break; - { - var lowerCasedName = registrationName.toLowerCase(); - possibleRegistrationNames[lowerCasedName] = registrationName; + case TransitionLane1: + case TransitionLane2: + case TransitionLane3: + case TransitionLane4: + case TransitionLane5: + case TransitionLane6: + case TransitionLane7: + case TransitionLane8: + case TransitionLane9: + case TransitionLane10: + case TransitionLane11: + case TransitionLane12: + case TransitionLane13: + case TransitionLane14: + case TransitionLane15: + case RetryLane1: + case RetryLane2: + case RetryLane3: + case RetryLane4: + lane = TransitionHydrationLane; + break; - if (registrationName === "onDoubleClick") { - possibleRegistrationNames.ondblclick = registrationName; - } - } + case IdleLane: + lane = IdleHydrationLane; + break; - for (var i = 0; i < dependencies.length; i++) { - allNativeEvents.add(dependencies[i]); - } -} + default: + // Everything else is already either a hydration lane, or shouldn't + // be retried at a hydration lane. + lane = NoLane; + break; + } + } // Check if the lane we chose is suspended. If so, that indicates that we + // already attempted and failed to hydrate at that level. Also check if we're + // already rendering that lane, which is rare but could happen. -var canUseDOM = !!( - typeof window !== "undefined" && - typeof window.document !== "undefined" && - typeof window.document.createElement !== "undefined" -); - -var hasReadOnlyValue = { - button: true, - checkbox: true, - image: true, - hidden: true, - radio: true, - reset: true, - submit: true -}; -function checkControlledValueProps(tagName, props) { - { - if ( - !( - hasReadOnlyValue[props.type] || - props.onChange || - props.onInput || - props.readOnly || - props.disabled || - props.value == null - ) - ) { - 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`." - ); - } + if ((lane & (root.suspendedLanes | renderLanes)) !== NoLane) { + // Give up trying to hydrate and fall back to client render. + return NoLane; + } - if ( - !( - props.onChange || - props.readOnly || - props.disabled || - props.checked == null - ) - ) { - 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`." - ); + return lane; } - } -} - -/* eslint-disable max-len */ + function addFiberToLanesMap(root, fiber, lanes) { + if (!isDevToolsPresent) { + return; + } -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"; -/* eslint-enable max-len */ + var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; -var ATTRIBUTE_NAME_CHAR = - ATTRIBUTE_NAME_START_CHAR + "\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040"; -var VALID_ATTRIBUTE_NAME_REGEX = new RegExp( - "^[" + ATTRIBUTE_NAME_START_CHAR + "][" + ATTRIBUTE_NAME_CHAR + "]*$" -); -var illegalAttributeNameCache = {}; -var validatedAttributeNameCache = {}; -function isAttributeNameSafe(attributeName) { - if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) { - return true; - } + while (lanes > 0) { + var index = laneToIndex(lanes); + var lane = 1 << index; + var updaters = pendingUpdatersLaneMap[index]; + updaters.add(fiber); + lanes &= ~lane; + } + } + function movePendingFibersToMemoized(root, lanes) { + if (!isDevToolsPresent) { + return; + } - if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) { - return false; - } + var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; + var memoizedUpdaters = root.memoizedUpdaters; - if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) { - validatedAttributeNameCache[attributeName] = true; - return true; - } + while (lanes > 0) { + var index = laneToIndex(lanes); + var lane = 1 << index; + var updaters = pendingUpdatersLaneMap[index]; - illegalAttributeNameCache[attributeName] = true; + if (updaters.size > 0) { + updaters.forEach(function (fiber) { + var alternate = fiber.alternate; - { - error("Invalid attribute name: `%s`", attributeName); - } + if (alternate === null || !memoizedUpdaters.has(alternate)) { + memoizedUpdaters.add(fiber); + } + }); + updaters.clear(); + } - return false; -} + lanes &= ~lane; + } + } + function addTransitionToLanesMap(root, transition, lane) { + if (enableTransitionTracing) { + var transitionLanesMap = root.transitionLanes; + var index = laneToIndex(lane); + var transitions = transitionLanesMap[index]; -/** - * Get the value for a attribute on a node. Only used in DEV for SSR validation. - * The third argument is used as a hint of what the expected value is. Some - * attributes have multiple equivalent values. - */ + if (transitions === null) { + transitions = new Set(); + } -function getValueForAttribute(node, name, expected) { - { - if (!isAttributeNameSafe(name)) { - return; + transitions.add(transition); + transitionLanesMap[index] = transitions; + } } + function getTransitionsForLanes(root, lanes) { + if (!enableTransitionTracing) { + return null; + } - if (!node.hasAttribute(name)) { - // shouldRemoveAttribute - switch (typeof expected) { - case "function": - case "symbol": - // eslint-disable-line - return expected; + var transitionsForLanes = []; - case "boolean": { - var prefix = name.toLowerCase().slice(0, 5); + while (lanes > 0) { + var index = laneToIndex(lanes); + var lane = 1 << index; + var transitions = root.transitionLanes[index]; - if (prefix !== "data-" && prefix !== "aria-") { - return expected; - } + if (transitions !== null) { + transitions.forEach(function (transition) { + transitionsForLanes.push(transition); + }); } + + lanes &= ~lane; + } + + if (transitionsForLanes.length === 0) { + return null; } - return expected === undefined ? undefined : null; + return transitionsForLanes; } + function clearTransitionsForLanes(root, lanes) { + if (!enableTransitionTracing) { + return; + } - var value = node.getAttribute(name); + while (lanes > 0) { + var index = laneToIndex(lanes); + var lane = 1 << index; + var transitions = root.transitionLanes[index]; - { - checkAttributeStringCoercion(expected, name); - } + if (transitions !== null) { + root.transitionLanes[index] = null; + } - if (value === "" + expected) { - return expected; + lanes &= ~lane; + } } - return value; - } -} -function getValueForAttributeOnCustomComponent(node, name, expected) { - { - if (!isAttributeNameSafe(name)) { - return; + var DiscreteEventPriority = SyncLane; + var ContinuousEventPriority = InputContinuousLane; + var DefaultEventPriority = DefaultLane; + var IdleEventPriority = IdleLane; + var currentUpdatePriority = NoLane; + function getCurrentUpdatePriority() { + return currentUpdatePriority; } + function setCurrentUpdatePriority(newPriority) { + currentUpdatePriority = newPriority; + } + function runWithPriority(priority, fn) { + var previousPriority = currentUpdatePriority; - if (!node.hasAttribute(name)) { - // shouldRemoveAttribute - switch (typeof expected) { - case "symbol": - case "object": - // Symbols and objects are ignored when they're emitted so - // it would be expected that they end up not having an attribute. - return expected; + try { + currentUpdatePriority = priority; + return fn(); + } finally { + currentUpdatePriority = previousPriority; + } + } + function higherEventPriority(a, b) { + return a !== 0 && a < b ? a : b; + } + function lowerEventPriority(a, b) { + return a === 0 || a > b ? a : b; + } + function isHigherEventPriority(a, b) { + return a !== 0 && a < b; + } + function lanesToEventPriority(lanes) { + var lane = getHighestPriorityLane(lanes); - case "function": - if (enableCustomElementPropertySupport) { - return expected; - } + if (!isHigherEventPriority(DiscreteEventPriority, lane)) { + return DiscreteEventPriority; + } - break; + if (!isHigherEventPriority(ContinuousEventPriority, lane)) { + return ContinuousEventPriority; + } - case "boolean": - if (enableCustomElementPropertySupport) { - if (expected === false) { - return expected; - } - } + if (includesNonIdleWork(lane)) { + return DefaultEventPriority; } - return expected === undefined ? undefined : null; + return IdleEventPriority; } - var value = node.getAttribute(name); + // $FlowFixMe[method-unbinding] + var hasOwnProperty = Object.prototype.hasOwnProperty; - if (enableCustomElementPropertySupport) { - if (value === "" && expected === true) { - return true; - } - } + /* + * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol + * and Temporal.* types. See https://github.com/facebook/react/pull/22064. + * + * The functions in this module will throw an easier-to-understand, + * easier-to-debug exception with a clear errors message message explaining the + * problem. (Instead of a confusing exception thrown inside the implementation + * of the `value` object). + */ + // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. + function typeName(value) { + { + // toStringTag is needed for namespaced types like Temporal.Instant + var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; + var type = + (hasToStringTag && value[Symbol.toStringTag]) || + value.constructor.name || + "Object"; // $FlowFixMe[incompatible-return] - { - checkAttributeStringCoercion(expected, name); - } + return type; + } + } // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. - if (value === "" + expected) { - return expected; + function willCoercionThrow(value) { + { + try { + testStringCoercion(value); + return false; + } catch (e) { + return true; + } + } } - return value; - } -} -function setValueForAttribute(node, name, value) { - if (isAttributeNameSafe(name)) { - // If the prop isn't in the special list, treat it as a simple attribute. - // shouldRemoveAttribute - if (value === null) { - node.removeAttribute(name); - return; + function testStringCoercion(value) { + // If you ended up here by following an exception call stack, here's what's + // happened: you supplied an object or symbol value to React (as a prop, key, + // DOM attribute, CSS property, string ref, etc.) and when React tried to + // coerce it to a string using `'' + value`, an exception was thrown. + // + // The most common types that will cause this exception are `Symbol` instances + // and Temporal objects like `Temporal.Instant`. But any object that has a + // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this + // exception. (Library authors do this to prevent users from using built-in + // numeric operators like `+` or comparison operators like `>=` because custom + // methods are needed to perform accurate arithmetic or comparison.) + // + // To fix the problem, coerce this object or symbol value to a string before + // passing it to React. The most reliable way is usually `String(value)`. + // + // To find which value is throwing, check the browser or debugger console. + // Before this exception was thrown, there should be `console.error` output + // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the + // problem and how that type was used: key, atrribute, input value prop, etc. + // In most cases, this console output also shows the component and its + // ancestor components where the exception happened. + // + // eslint-disable-next-line react-internal/safe-string-coercion + return "" + value; } - switch (typeof value) { - case "undefined": - case "function": - case "symbol": - // eslint-disable-line - node.removeAttribute(name); - return; - - case "boolean": { - var prefix = name.toLowerCase().slice(0, 5); + function checkAttributeStringCoercion(value, attributeName) { + { + if (willCoercionThrow(value)) { + error( + "The provided `%s` attribute is an unsupported type %s." + + " This value must be coerced to a string before using it here.", + attributeName, + typeName(value) + ); - if (prefix !== "data-" && prefix !== "aria-") { - node.removeAttribute(name); - return; + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } } } + function checkKeyStringCoercion(value) { + { + if (willCoercionThrow(value)) { + error( + "The provided key is an unsupported type %s." + + " This value must be coerced to a string before using it here.", + typeName(value) + ); - { - checkAttributeStringCoercion(value, name); + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + } + } } + function checkPropStringCoercion(value, propName) { + { + if (willCoercionThrow(value)) { + error( + "The provided `%s` prop is an unsupported type %s." + + " This value must be coerced to a string before using it here.", + propName, + typeName(value) + ); - node.setAttribute(name, enableTrustedTypesIntegration ? value : "" + value); - } -} -function setValueForKnownAttribute(node, name, value) { - if (value === null) { - node.removeAttribute(name); - return; - } - - switch (typeof value) { - case "undefined": - case "function": - case "symbol": - case "boolean": { - node.removeAttribute(name); - return; + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + } + } } - } - - { - checkAttributeStringCoercion(value, name); - } + function checkCSSPropertyStringCoercion(value, propName) { + { + if (willCoercionThrow(value)) { + error( + "The provided `%s` CSS property is an unsupported type %s." + + " This value must be coerced to a string before using it here.", + propName, + typeName(value) + ); - node.setAttribute(name, enableTrustedTypesIntegration ? value : "" + value); -} -function setValueForNamespacedAttribute(node, namespace, name, value) { - if (value === null) { - node.removeAttribute(name); - return; - } - - switch (typeof value) { - case "undefined": - case "function": - case "symbol": - case "boolean": { - node.removeAttribute(name); - return; + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + } + } } - } - - { - checkAttributeStringCoercion(value, name); - } + function checkHtmlStringCoercion(value) { + { + if (willCoercionThrow(value)) { + error( + "The provided HTML markup uses a value of unsupported type %s." + + " This value must be coerced to a string before using it here.", + typeName(value) + ); - node.setAttributeNS( - namespace, - name, - enableTrustedTypesIntegration ? value : "" + value - ); -} -function setValueForPropertyOnCustomComponent(node, name, value) { - if (name[0] === "o" && name[1] === "n") { - var useCapture = name.endsWith("Capture"); - var eventName = name.slice(2, useCapture ? name.length - 7 : undefined); - var prevProps = getFiberCurrentPropsFromNode(node); - var prevValue = prevProps != null ? prevProps[name] : null; - - if (typeof prevValue === "function") { - node.removeEventListener(eventName, prevValue, useCapture); - } - - if (typeof value === "function") { - if (typeof prevValue !== "function" && prevValue !== null) { - // If we previously assigned a non-function type into this node, then - // remove it when switching to event listener mode. - if (name in node) { - node[name] = null; - } else if (node.hasAttribute(name)) { - node.removeAttribute(name); + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } - } // $FlowFixMe[incompatible-cast] value can't be casted to EventListener. - - node.addEventListener(eventName, value, useCapture); - return; + } } - } - - if (name in node) { - node[name] = value; - return; - } - - if (value === true) { - node.setAttribute(name, ""); - return; - } // From here, it's the same as any attribute - - setValueForAttribute(node, name, value); -} + function checkFormFieldValueStringCoercion(value) { + { + if (willCoercionThrow(value)) { + error( + "Form field values (value, checked, defaultValue, or defaultChecked props)" + + " must be strings, not %s." + + " This value must be coerced to a string before using it here.", + typeName(value) + ); -var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher; -var prefix; -function describeBuiltInComponentFrame(name, source, ownerFn) { - { - if (prefix === undefined) { - // Extract the VM specific prefix used by each line. - try { - throw Error(); - } catch (x) { - var match = x.stack.trim().match(/\n( *(at )?)/); - prefix = (match && match[1]) || ""; + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + } } - } // We use the prefix to ensure our stacks line up with native stack frames. + } - return "\n" + prefix + name; - } -} -var reentry = false; -var componentFrameCache; + var allNativeEvents = new Set(); -{ - var PossiblyWeakMap$2 = typeof WeakMap === "function" ? WeakMap : Map; - componentFrameCache = new PossiblyWeakMap$2(); -} + { + allNativeEvents.add("beforeblur"); + allNativeEvents.add("afterblur"); + } + /** + * Mapping from registration name to event name + */ -function describeNativeComponentFrame(fn, construct) { - // If something asked for a stack inside a fake render, it should get ignored. - if (!fn || reentry) { - return ""; - } + var registrationNameDependencies = {}; + /** + * Mapping from lowercase registration names to the properly cased version, + * used to warn in the case of missing event handlers. Available + * only in __DEV__. + * @type {Object} + */ - { - var frame = componentFrameCache.get(fn); + var possibleRegistrationNames = {}; // Trust the developer to only use possibleRegistrationNames in true - if (frame !== undefined) { - return frame; + function registerTwoPhaseEvent(registrationName, dependencies) { + registerDirectEvent(registrationName, dependencies); + registerDirectEvent(registrationName + "Capture", dependencies); } - } + function registerDirectEvent(registrationName, dependencies) { + { + if (registrationNameDependencies[registrationName]) { + error( + "EventRegistry: More than one plugin attempted to publish the same " + + "registration name, `%s`.", + registrationName + ); + } + } - var control; - reentry = true; - var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. + registrationNameDependencies[registrationName] = dependencies; - Error.prepareStackTrace = undefined; - var previousDispatcher; + { + var lowerCasedName = registrationName.toLowerCase(); + possibleRegistrationNames[lowerCasedName] = registrationName; - { - previousDispatcher = ReactCurrentDispatcher$2.current; // Set the dispatcher in DEV because this might be call in the render function - // for warnings. + if (registrationName === "onDoubleClick") { + possibleRegistrationNames.ondblclick = registrationName; + } + } - ReactCurrentDispatcher$2.current = null; - disableLogs(); - } + for (var i = 0; i < dependencies.length; i++) { + allNativeEvents.add(dependencies[i]); + } + } - try { - // This should throw. - if (construct) { - // Something should be setting the props in the constructor. - var Fake = function () { - throw Error(); - }; // $FlowFixMe[prop-missing] + var canUseDOM = !!( + typeof window !== "undefined" && + typeof window.document !== "undefined" && + typeof window.document.createElement !== "undefined" + ); - Object.defineProperty(Fake.prototype, "props", { - set: function () { - // We use a throwing setter instead of frozen or non-writable props - // because that won't throw in a non-strict mode function. - throw Error(); - } - }); + var hasReadOnlyValue = { + button: true, + checkbox: true, + image: true, + hidden: true, + radio: true, + reset: true, + submit: true + }; + function checkControlledValueProps(tagName, props) { + { + if ( + !( + hasReadOnlyValue[props.type] || + props.onChange || + props.onInput || + props.readOnly || + props.disabled || + props.value == null + ) + ) { + 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`." + ); + } - if (typeof Reflect === "object" && Reflect.construct) { - // We construct a different control for this case to include any extra - // frames added by the construct call. - try { - Reflect.construct(Fake, []); - } catch (x) { - control = x; + if ( + !( + props.onChange || + props.readOnly || + props.disabled || + props.checked == null + ) + ) { + 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`." + ); } + } + } - Reflect.construct(fn, [], Fake); - } else { - try { - Fake.call(); - } catch (x) { - control = x; - } // $FlowFixMe[prop-missing] found when upgrading Flow + /* eslint-disable max-len */ - fn.call(Fake.prototype); + 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"; + /* eslint-enable max-len */ + + var ATTRIBUTE_NAME_CHAR = + ATTRIBUTE_NAME_START_CHAR + + "\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040"; + var VALID_ATTRIBUTE_NAME_REGEX = new RegExp( + "^[" + ATTRIBUTE_NAME_START_CHAR + "][" + ATTRIBUTE_NAME_CHAR + "]*$" + ); + var illegalAttributeNameCache = {}; + var validatedAttributeNameCache = {}; + function isAttributeNameSafe(attributeName) { + if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) { + return true; } - } else { - try { - throw Error(); - } catch (x) { - control = x; - } // TODO(luna): This will currently only throw if the function component - // tries to access React/ReactDOM/props. We should probably make this throw - // in simple components too - - var maybePromise = fn(); // If the function component returns a promise, it's likely an async - // component, which we don't yet support. Attach a noop catch handler to - // silence the error. - // TODO: Implement component stacks for async client components? - - if (maybePromise && typeof maybePromise.catch === "function") { - maybePromise.catch(function () {}); - } - } - } catch (sample) { - // This is inlined manually because closure doesn't do it for us. - if (sample && control && typeof sample.stack === "string") { - // This extracts the first frame from the sample that isn't also in the control. - // Skipping one frame that we assume is the frame that calls the two. - var sampleLines = sample.stack.split("\n"); - var controlLines = control.stack.split("\n"); - var s = sampleLines.length - 1; - var c = controlLines.length - 1; - - while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { - // We expect at least one stack frame to be shared. - // Typically this will be the root most one. However, stack frames may be - // cut off due to maximum stack limits. In this case, one maybe cut off - // earlier than the other. We assume that the sample is longer or the same - // and there for cut off earlier. So we should find the root most frame in - // the sample somewhere in the control. - c--; - } - - for (; s >= 1 && c >= 0; s--, c--) { - // Next we find the first one that isn't the same which should be the - // frame that called our sample function and the control. - if (sampleLines[s] !== controlLines[c]) { - // In V8, the first line is describing the message but other VMs don't. - // If we're about to return the first line, and the control is also on the same - // line, that's a pretty good indicator that our sample threw at same line as - // the control. I.e. before we entered the sample frame. So we ignore this result. - // This can happen if you passed a class to function component, or non-function. - if (s !== 1 || c !== 1) { - do { - s--; - c--; // We may still have similar intermediate frames from the construct call. - // The next one that isn't the same should be our match though. - - if (c < 0 || sampleLines[s] !== controlLines[c]) { - // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. - var _frame = "\n" + sampleLines[s].replace(" at new ", " at "); // If our component frame is labeled "" - // but we have a user-provided "displayName" - // splice it in to make the stack more readable. - - if (fn.displayName && _frame.includes("")) { - _frame = _frame.replace("", fn.displayName); - } - { - if (typeof fn === "function") { - componentFrameCache.set(fn, _frame); - } - } // Return the line we found. + if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) { + return false; + } - return _frame; - } - } while (s >= 1 && c >= 0); - } + if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) { + validatedAttributeNameCache[attributeName] = true; + return true; + } - break; - } + illegalAttributeNameCache[attributeName] = true; + + { + error("Invalid attribute name: `%s`", attributeName); } - } - } finally { - reentry = false; - { - ReactCurrentDispatcher$2.current = previousDispatcher; - reenableLogs(); + return false; } - Error.prepareStackTrace = previousPrepareStackTrace; - } // Fallback to just using the name if we couldn't make it throw. + /** + * Get the value for a attribute on a node. Only used in DEV for SSR validation. + * The third argument is used as a hint of what the expected value is. Some + * attributes have multiple equivalent values. + */ - var name = fn ? fn.displayName || fn.name : ""; - var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ""; + function getValueForAttribute(node, name, expected) { + { + if (!isAttributeNameSafe(name)) { + return; + } - { - if (typeof fn === "function") { - componentFrameCache.set(fn, syntheticFrame); - } - } + if (!node.hasAttribute(name)) { + // shouldRemoveAttribute + switch (typeof expected) { + case "function": + case "symbol": + // eslint-disable-line + return expected; - return syntheticFrame; -} + case "boolean": { + var prefix = name.toLowerCase().slice(0, 5); -function describeClassComponentFrame(ctor, source, ownerFn) { - { - return describeNativeComponentFrame(ctor, true); - } -} -function describeFunctionComponentFrame(fn, source, ownerFn) { - { - return describeNativeComponentFrame(fn, false); - } -} + if (prefix !== "data-" && prefix !== "aria-") { + return expected; + } + } + } -function shouldConstruct$1(Component) { - var prototype = Component.prototype; - return !!(prototype && prototype.isReactComponent); -} + return expected === undefined ? undefined : null; + } -function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { - if (type == null) { - return ""; - } + var value = node.getAttribute(name); - if (typeof type === "function") { - { - return describeNativeComponentFrame(type, shouldConstruct$1(type)); + { + checkAttributeStringCoercion(expected, name); + } + + if (value === "" + expected) { + return expected; + } + + return value; + } } - } + function getValueForAttributeOnCustomComponent(node, name, expected) { + { + if (!isAttributeNameSafe(name)) { + return; + } - if (typeof type === "string") { - return describeBuiltInComponentFrame(type); - } + if (!node.hasAttribute(name)) { + // shouldRemoveAttribute + switch (typeof expected) { + case "symbol": + case "object": + // Symbols and objects are ignored when they're emitted so + // it would be expected that they end up not having an attribute. + return expected; - switch (type) { - case REACT_SUSPENSE_TYPE: - return describeBuiltInComponentFrame("Suspense"); + case "function": + if (enableCustomElementPropertySupport) { + return expected; + } - case REACT_SUSPENSE_LIST_TYPE: - return describeBuiltInComponentFrame("SuspenseList"); - } + break; - if (typeof type === "object") { - switch (type.$$typeof) { - case REACT_FORWARD_REF_TYPE: - return describeFunctionComponentFrame(type.render); + case "boolean": + if (enableCustomElementPropertySupport) { + if (expected === false) { + return expected; + } + } + } - case REACT_MEMO_TYPE: - // Memo may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); + return expected === undefined ? undefined : null; + } - case REACT_LAZY_TYPE: { - var lazyComponent = type; - var payload = lazyComponent._payload; - var init = lazyComponent._init; + var value = node.getAttribute(name); - try { - // Lazy may contain any component type so we recursively resolve it. - return describeUnknownElementTypeFrameInDEV( - init(payload), - source, - ownerFn - ); - } catch (x) {} + if (enableCustomElementPropertySupport) { + if (value === "" && expected === true) { + return true; + } + } + + { + checkAttributeStringCoercion(expected, name); + } + + if (value === "" + expected) { + return expected; + } + + return value; } } - } + function setValueForAttribute(node, name, value) { + if (isAttributeNameSafe(name)) { + // If the prop isn't in the special list, treat it as a simple attribute. + // shouldRemoveAttribute + if (value === null) { + node.removeAttribute(name); + return; + } - return ""; -} + switch (typeof value) { + case "undefined": + case "function": + case "symbol": + // eslint-disable-line + node.removeAttribute(name); + return; -function describeFiber(fiber) { - switch (fiber.tag) { - case HostHoistable: - case HostSingleton: - case HostComponent: - return describeBuiltInComponentFrame(fiber.type); + case "boolean": { + var prefix = name.toLowerCase().slice(0, 5); - case LazyComponent: - return describeBuiltInComponentFrame("Lazy"); + if (prefix !== "data-" && prefix !== "aria-") { + node.removeAttribute(name); + return; + } + } + } - case SuspenseComponent: - return describeBuiltInComponentFrame("Suspense"); + { + checkAttributeStringCoercion(value, name); + } - case SuspenseListComponent: - return describeBuiltInComponentFrame("SuspenseList"); + node.setAttribute( + name, + enableTrustedTypesIntegration ? value : "" + value + ); + } + } + function setValueForKnownAttribute(node, name, value) { + if (value === null) { + node.removeAttribute(name); + return; + } - case FunctionComponent: - case IndeterminateComponent: - case SimpleMemoComponent: - return describeFunctionComponentFrame(fiber.type); + switch (typeof value) { + case "undefined": + case "function": + case "symbol": + case "boolean": { + node.removeAttribute(name); + return; + } + } - case ForwardRef: - return describeFunctionComponentFrame(fiber.type.render); + { + checkAttributeStringCoercion(value, name); + } - case ClassComponent: - return describeClassComponentFrame(fiber.type); + node.setAttribute( + name, + enableTrustedTypesIntegration ? value : "" + value + ); + } + function setValueForNamespacedAttribute(node, namespace, name, value) { + if (value === null) { + node.removeAttribute(name); + return; + } - default: - return ""; - } -} + switch (typeof value) { + case "undefined": + case "function": + case "symbol": + case "boolean": { + node.removeAttribute(name); + return; + } + } -function getStackByFiberInDevAndProd(workInProgress) { - try { - var info = ""; - var node = workInProgress; + { + checkAttributeStringCoercion(value, name); + } - do { - info += describeFiber(node); // $FlowFixMe[incompatible-type] we bail out when we get a null + node.setAttributeNS( + namespace, + name, + enableTrustedTypesIntegration ? value : "" + value + ); + } + function setValueForPropertyOnCustomComponent(node, name, value) { + if (name[0] === "o" && name[1] === "n") { + var useCapture = name.endsWith("Capture"); + var eventName = name.slice(2, useCapture ? name.length - 7 : undefined); + var prevProps = getFiberCurrentPropsFromNode(node); + var prevValue = prevProps != null ? prevProps[name] : null; - node = node.return; - } while (node); + if (typeof prevValue === "function") { + node.removeEventListener(eventName, prevValue, useCapture); + } - return info; - } catch (x) { - return "\nError generating stack: " + x.message + "\n" + x.stack; - } -} + if (typeof value === "function") { + if (typeof prevValue !== "function" && prevValue !== null) { + // If we previously assigned a non-function type into this node, then + // remove it when switching to event listener mode. + if (name in node) { + node[name] = null; + } else if (node.hasAttribute(name)) { + node.removeAttribute(name); + } + } // $FlowFixMe[incompatible-cast] value can't be casted to EventListener. -var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; -var current = null; -var isRendering = false; -function getCurrentFiberOwnerNameInDevOrNull() { - { - if (current === null) { - return null; + node.addEventListener(eventName, value, useCapture); + return; + } + } + + if (name in node) { + node[name] = value; + return; + } + + if (value === true) { + node.setAttribute(name, ""); + return; + } // From here, it's the same as any attribute + + setValueForAttribute(node, name, value); } - var owner = current._debugOwner; + var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher; + var prefix; + function describeBuiltInComponentFrame(name, source, ownerFn) { + { + if (prefix === undefined) { + // Extract the VM specific prefix used by each line. + try { + throw Error(); + } catch (x) { + var match = x.stack.trim().match(/\n( *(at )?)/); + prefix = (match && match[1]) || ""; + } + } // We use the prefix to ensure our stacks line up with native stack frames. - if (owner !== null && typeof owner !== "undefined") { - return getComponentNameFromFiber(owner); + return "\n" + prefix + name; + } } - } + var reentry = false; + var componentFrameCache; - return null; -} + { + var PossiblyWeakMap$2 = typeof WeakMap === "function" ? WeakMap : Map; + componentFrameCache = new PossiblyWeakMap$2(); + } -function getCurrentFiberStackInDev() { - { - if (current === null) { - return ""; - } // Safe because if current fiber exists, we are reconciling, - // and it is guaranteed to be the work-in-progress version. + function describeNativeComponentFrame(fn, construct) { + // If something asked for a stack inside a fake render, it should get ignored. + if (!fn || reentry) { + return ""; + } - return getStackByFiberInDevAndProd(current); - } -} + { + var frame = componentFrameCache.get(fn); -function resetCurrentFiber() { - { - ReactDebugCurrentFrame$1.getCurrentStack = null; - current = null; - isRendering = false; - } -} -function setCurrentFiber(fiber) { - { - ReactDebugCurrentFrame$1.getCurrentStack = - fiber === null ? null : getCurrentFiberStackInDev; - current = fiber; - isRendering = false; - } -} -function getCurrentFiber() { - { - return current; - } -} -function setIsRendering(rendering) { - { - isRendering = rendering; - } -} + if (frame !== undefined) { + return frame; + } + } -// around this limitation, we use an opaque type that can only be obtained by -// passing the value through getToStringValue first. + var control; + reentry = true; + var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. -function toString(value) { - // The coercion safety check is performed in getToStringValue(). - // eslint-disable-next-line react-internal/safe-string-coercion - return "" + value; -} -function getToStringValue(value) { - switch (typeof value) { - case "boolean": - case "number": - case "string": - case "undefined": - return value; + Error.prepareStackTrace = undefined; + var previousDispatcher; - case "object": { - checkFormFieldValueStringCoercion(value); + previousDispatcher = ReactCurrentDispatcher$2.current; // Set the dispatcher in DEV because this might be call in the render function + // for warnings. + + ReactCurrentDispatcher$2.current = null; + disableLogs(); } - return value; + try { + // This should throw. + if (construct) { + // Something should be setting the props in the constructor. + var Fake = function () { + throw Error(); + }; // $FlowFixMe[prop-missing] + + Object.defineProperty(Fake.prototype, "props", { + set: function () { + // We use a throwing setter instead of frozen or non-writable props + // because that won't throw in a non-strict mode function. + throw Error(); + } + }); - default: - // function, symbol are assigned as empty strings - return ""; - } -} + if (typeof Reflect === "object" && Reflect.construct) { + // We construct a different control for this case to include any extra + // frames added by the construct call. + try { + Reflect.construct(Fake, []); + } catch (x) { + control = x; + } -function isCheckable(elem) { - var type = elem.type; - var nodeName = elem.nodeName; - return ( - nodeName && - nodeName.toLowerCase() === "input" && - (type === "checkbox" || type === "radio") - ); -} + Reflect.construct(fn, [], Fake); + } else { + try { + Fake.call(); + } catch (x) { + control = x; + } // $FlowFixMe[prop-missing] found when upgrading Flow -function getTracker(node) { - return node._valueTracker; -} + fn.call(Fake.prototype); + } + } else { + try { + throw Error(); + } catch (x) { + control = x; + } // TODO(luna): This will currently only throw if the function component + // tries to access React/ReactDOM/props. We should probably make this throw + // in simple components too + + var maybePromise = fn(); // If the function component returns a promise, it's likely an async + // component, which we don't yet support. Attach a noop catch handler to + // silence the error. + // TODO: Implement component stacks for async client components? + + if (maybePromise && typeof maybePromise.catch === "function") { + maybePromise.catch(function () {}); + } + } + } catch (sample) { + // This is inlined manually because closure doesn't do it for us. + if (sample && control && typeof sample.stack === "string") { + // This extracts the first frame from the sample that isn't also in the control. + // Skipping one frame that we assume is the frame that calls the two. + var sampleLines = sample.stack.split("\n"); + var controlLines = control.stack.split("\n"); + var s = sampleLines.length - 1; + var c = controlLines.length - 1; + + while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { + // We expect at least one stack frame to be shared. + // Typically this will be the root most one. However, stack frames may be + // cut off due to maximum stack limits. In this case, one maybe cut off + // earlier than the other. We assume that the sample is longer or the same + // and there for cut off earlier. So we should find the root most frame in + // the sample somewhere in the control. + c--; + } + + for (; s >= 1 && c >= 0; s--, c--) { + // Next we find the first one that isn't the same which should be the + // frame that called our sample function and the control. + if (sampleLines[s] !== controlLines[c]) { + // In V8, the first line is describing the message but other VMs don't. + // If we're about to return the first line, and the control is also on the same + // line, that's a pretty good indicator that our sample threw at same line as + // the control. I.e. before we entered the sample frame. So we ignore this result. + // This can happen if you passed a class to function component, or non-function. + if (s !== 1 || c !== 1) { + do { + s--; + c--; // We may still have similar intermediate frames from the construct call. + // The next one that isn't the same should be our match though. + + if (c < 0 || sampleLines[s] !== controlLines[c]) { + // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. + var _frame = + "\n" + sampleLines[s].replace(" at new ", " at "); // If our component frame is labeled "" + // but we have a user-provided "displayName" + // splice it in to make the stack more readable. + + if (fn.displayName && _frame.includes("")) { + _frame = _frame.replace("", fn.displayName); + } -function detachTracker(node) { - node._valueTracker = null; -} + { + if (typeof fn === "function") { + componentFrameCache.set(fn, _frame); + } + } // Return the line we found. -function getValueFromNode(node) { - var value = ""; + return _frame; + } + } while (s >= 1 && c >= 0); + } + + break; + } + } + } + } finally { + reentry = false; - if (!node) { - return value; - } + { + ReactCurrentDispatcher$2.current = previousDispatcher; + reenableLogs(); + } - if (isCheckable(node)) { - value = node.checked ? "true" : "false"; - } else { - value = node.value; - } + Error.prepareStackTrace = previousPrepareStackTrace; + } // Fallback to just using the name if we couldn't make it throw. - return value; -} + var name = fn ? fn.displayName || fn.name : ""; + var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ""; -function trackValueOnNode(node) { - var valueField = isCheckable(node) ? "checked" : "value"; - var descriptor = Object.getOwnPropertyDescriptor( - node.constructor.prototype, - valueField - ); - - { - checkFormFieldValueStringCoercion(node[valueField]); - } - - var currentValue = "" + node[valueField]; // if someone has already defined a value or Safari, then bail - // and don't track value will cause over reporting of changes, - // but it's better then a hard failure - // (needed for certain tests that spyOn input values and Safari) - - if ( - node.hasOwnProperty(valueField) || - typeof descriptor === "undefined" || - typeof descriptor.get !== "function" || - typeof descriptor.set !== "function" - ) { - return; - } - - var get = descriptor.get, - set = descriptor.set; - Object.defineProperty(node, valueField, { - configurable: true, - // $FlowFixMe[missing-this-annot] - get: function () { - return get.call(this); - }, - // $FlowFixMe[missing-local-annot] - // $FlowFixMe[missing-this-annot] - set: function (value) { { - checkFormFieldValueStringCoercion(value); + if (typeof fn === "function") { + componentFrameCache.set(fn, syntheticFrame); + } } - currentValue = "" + value; - set.call(this, value); + return syntheticFrame; } - }); // We could've passed this the first time - // but it triggers a bug in IE11 and Edge 14/15. - // Calling defineProperty() again should be equivalent. - // https://github.com/facebook/react/issues/11768 - Object.defineProperty(node, valueField, { - enumerable: descriptor.enumerable - }); - var tracker = { - getValue: function () { - return currentValue; - }, - setValue: function (value) { + function describeClassComponentFrame(ctor, source, ownerFn) { + { + return describeNativeComponentFrame(ctor, true); + } + } + function describeFunctionComponentFrame(fn, source, ownerFn) { { - checkFormFieldValueStringCoercion(value); + return describeNativeComponentFrame(fn, false); } + } - currentValue = "" + value; - }, - stopTracking: function () { - detachTracker(node); - delete node[valueField]; + function shouldConstruct$1(Component) { + var prototype = Component.prototype; + return !!(prototype && prototype.isReactComponent); } - }; - return tracker; -} -function track(node) { - if (getTracker(node)) { - return; - } + function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { + if (type == null) { + return ""; + } - node._valueTracker = trackValueOnNode(node); -} -function updateValueIfChanged(node) { - if (!node) { - return false; - } + if (typeof type === "function") { + { + return describeNativeComponentFrame(type, shouldConstruct$1(type)); + } + } - var tracker = getTracker(node); // if there is no tracker at this point it's unlikely - // that trying again will succeed + if (typeof type === "string") { + return describeBuiltInComponentFrame(type); + } - if (!tracker) { - return true; - } + switch (type) { + case REACT_SUSPENSE_TYPE: + return describeBuiltInComponentFrame("Suspense"); - var lastValue = tracker.getValue(); - var nextValue = getValueFromNode(node); + case REACT_SUSPENSE_LIST_TYPE: + return describeBuiltInComponentFrame("SuspenseList"); + } - if (nextValue !== lastValue) { - tracker.setValue(nextValue); - return true; - } + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_FORWARD_REF_TYPE: + return describeFunctionComponentFrame(type.render); - return false; -} + case REACT_MEMO_TYPE: + // Memo may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + type.type, + source, + ownerFn + ); -function getActiveElement(doc) { - doc = doc || (typeof document !== "undefined" ? document : undefined); + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - if (typeof doc === "undefined") { - return null; - } + try { + // Lazy may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + init(payload), + source, + ownerFn + ); + } catch (x) {} + } + } + } - try { - return doc.activeElement || doc.body; - } catch (e) { - return doc.body; - } -} + return ""; + } -// When passing user input into querySelector(All) the embedded string must not alter -// the semantics of the query. This escape function is safe to use when we know the -// provided value is going to be wrapped in double quotes as part of an attribute selector -// Do not use it anywhere else -// we escape double quotes and backslashes -var escapeSelectorAttributeValueInsideDoubleQuotesRegex = /[\n\"\\]/g; -function escapeSelectorAttributeValueInsideDoubleQuotes(value) { - return value.replace( - escapeSelectorAttributeValueInsideDoubleQuotesRegex, - function (ch) { - return "\\" + ch.charCodeAt(0).toString(16) + " "; - } - ); -} + function describeFiber(fiber) { + switch (fiber.tag) { + case HostHoistable: + case HostSingleton: + case HostComponent: + return describeBuiltInComponentFrame(fiber.type); -var didWarnValueDefaultValue$1 = false; -var didWarnCheckedDefaultChecked = false; -/** - * Implements an host component that allows setting these optional - * props: `checked`, `value`, `defaultChecked`, and `defaultValue`. - * - * If `checked` or `value` are not supplied (or null/undefined), user actions - * that affect the checked state or value will trigger updates to the element. - * - * If they are supplied (and not null/undefined), the rendered element will not - * trigger updates to the element. Instead, the props must change in order for - * the rendered element to be updated. - * - * The rendered element will be initialized as unchecked (or `defaultChecked`) - * with an empty value (or `defaultValue`). - * - * See http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html - */ + case LazyComponent: + return describeBuiltInComponentFrame("Lazy"); -function validateInputProps(element, props) { - { - // Normally we check for undefined and null the same, but explicitly specifying both - // properties, at all is probably worth warning for. We could move this either direction - // and just make it ok to pass null or just check hasOwnProperty. - if ( - props.checked !== undefined && - props.defaultChecked !== undefined && - !didWarnCheckedDefaultChecked - ) { - 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 - ); + case SuspenseComponent: + return describeBuiltInComponentFrame("Suspense"); - didWarnCheckedDefaultChecked = true; - } + case SuspenseListComponent: + return describeBuiltInComponentFrame("SuspenseList"); - if ( - props.value !== undefined && - props.defaultValue !== undefined && - !didWarnValueDefaultValue$1 - ) { - 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 - ); + case FunctionComponent: + case IndeterminateComponent: + case SimpleMemoComponent: + return describeFunctionComponentFrame(fiber.type); - didWarnValueDefaultValue$1 = true; - } - } -} -function updateInput( - element, - value, - defaultValue, - lastDefaultValue, - checked, - defaultChecked, - type, - name -) { - var node = element; // Temporarily disconnect the input from any radio buttons. - // Changing the type or name as the same time as changing the checked value - // needs to be atomically applied. We can only ensure that by disconnecting - // the name while do the mutations and then reapply the name after that's done. - - node.name = ""; - - if ( - type != null && - typeof type !== "function" && - typeof type !== "symbol" && - typeof type !== "boolean" - ) { - { - checkAttributeStringCoercion(type, "type"); - } + case ForwardRef: + return describeFunctionComponentFrame(fiber.type.render); - node.type = type; - } else { - node.removeAttribute("type"); - } + case ClassComponent: + return describeClassComponentFrame(fiber.type); - if (value != null) { - if (type === "number") { - if ( - // $FlowFixMe[incompatible-type] - (value === 0 && node.value === "") || // We explicitly want to coerce to number here if possible. - // eslint-disable-next-line - node.value != value - ) { - node.value = toString(getToStringValue(value)); - } - } else if (node.value !== toString(getToStringValue(value))) { - node.value = toString(getToStringValue(value)); - } - } else if (type === "submit" || type === "reset") { - // Submit/reset inputs need the attribute removed completely to avoid - // blank-text buttons. - node.removeAttribute("value"); - } - - if (disableInputAttributeSyncing) { - // When not syncing the value attribute, React only assigns a new value - // whenever the defaultValue React prop has changed. When not present, - // React does nothing - if (defaultValue != null) { - setDefaultValue(node, type, getToStringValue(defaultValue)); - } else if (lastDefaultValue != null) { - node.removeAttribute("value"); - } - } else { - // When syncing the value attribute, the value comes from a cascade of - // properties: - // 1. The value React property - // 2. The defaultValue React property - // 3. Otherwise there should be no change - if (value != null) { - setDefaultValue(node, type, getToStringValue(value)); - } else if (defaultValue != null) { - setDefaultValue(node, type, getToStringValue(defaultValue)); - } else if (lastDefaultValue != null) { - node.removeAttribute("value"); - } - } - - if (disableInputAttributeSyncing) { - // When not syncing the checked attribute, the attribute is directly - // controllable from the defaultValue React property. It needs to be - // updated as new props come in. - if (defaultChecked == null) { - node.removeAttribute("checked"); - } else { - node.defaultChecked = !!defaultChecked; - } - } else { - // When syncing the checked attribute, it only changes when it needs - // to be removed, such as transitioning from a checkbox into a text input - if (checked == null && defaultChecked != null) { - node.defaultChecked = !!defaultChecked; - } - } - - if (checked != null) { - // Important to set this even if it's not a change in order to update input - // value tracking with radio buttons - // TODO: Should really update input value tracking for the whole radio - // button group in an effect or something (similar to #27024) - node.checked = - checked && typeof checked !== "function" && typeof checked !== "symbol"; - } - - if ( - name != null && - typeof name !== "function" && - typeof name !== "symbol" && - typeof name !== "boolean" - ) { - { - checkAttributeStringCoercion(name, "name"); + default: + return ""; + } } - node.name = toString(getToStringValue(name)); - } else { - node.removeAttribute("name"); - } -} -function initInput( - element, - value, - defaultValue, - checked, - defaultChecked, - type, - name, - isHydrating -) { - var node = element; - - if ( - type != null && - typeof type !== "function" && - typeof type !== "symbol" && - typeof type !== "boolean" - ) { - { - checkAttributeStringCoercion(type, "type"); - } + function getStackByFiberInDevAndProd(workInProgress) { + try { + var info = ""; + var node = workInProgress; - node.type = type; - } + do { + info += describeFiber(node); // $FlowFixMe[incompatible-type] we bail out when we get a null - if (value != null || defaultValue != null) { - var isButton = type === "submit" || type === "reset"; // Avoid setting value attribute on submit/reset inputs as it overrides the - // default value provided by the browser. See: #12872 + node = node.return; + } while (node); - if (isButton && (value === undefined || value === null)) { - return; + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; + } } - var defaultValueStr = - defaultValue != null ? toString(getToStringValue(defaultValue)) : ""; - var initialValue = - value != null ? toString(getToStringValue(value)) : defaultValueStr; // Do not assign value if it is already set. This prevents user text input - // from being lost during SSR hydration. - - if (!isHydrating) { - if (disableInputAttributeSyncing) { - // When not syncing the value attribute, the value property points - // directly to the React prop. Only assign it if it exists. - if (value != null) { - // Always assign on buttons so that it is possible to assign an - // empty string to clear button text. - // - // Otherwise, do not re-assign the value property if is empty. This - // potentially avoids a DOM write and prevents Firefox (~60.0.1) from - // prematurely marking required inputs as invalid. Equality is compared - // to the current value in case the browser provided value is not an - // empty string. - if (isButton || toString(getToStringValue(value)) !== node.value) { - node.value = toString(getToStringValue(value)); - } + var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; + var current = null; + var isRendering = false; + function getCurrentFiberOwnerNameInDevOrNull() { + { + if (current === null) { + return null; } - } else { - // When syncing the value attribute, the value property should use - // the wrapperState._initialValue property. This uses: - // - // 1. The value React property when present - // 2. The defaultValue React property when present - // 3. An empty string - if (initialValue !== node.value) { - node.value = initialValue; + + var owner = current._debugOwner; + + if (owner !== null && typeof owner !== "undefined") { + return getComponentNameFromFiber(owner); } } + + return null; } - if (disableInputAttributeSyncing) { - // When not syncing the value attribute, assign the value attribute - // directly from the defaultValue React property (when present) - if (defaultValue != null) { - node.defaultValue = defaultValueStr; + function getCurrentFiberStackInDev() { + { + if (current === null) { + return ""; + } // Safe because if current fiber exists, we are reconciling, + // and it is guaranteed to be the work-in-progress version. + + return getStackByFiberInDevAndProd(current); } - } else { - // Otherwise, the value attribute is synchronized to the property, - // so we assign defaultValue to the same thing as the value property - // assignment step above. - node.defaultValue = initialValue; - } - } // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug - // this is needed to work around a chrome bug where setting defaultChecked - // will sometimes influence the value of checked (even after detachment). - // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416 - // We need to temporarily unset name to avoid disrupting radio button groups. - - var checkedOrDefault = checked != null ? checked : defaultChecked; // TODO: This 'function' or 'symbol' check isn't replicated in other places - // so this semantic is inconsistent. - - var initialChecked = - typeof checkedOrDefault !== "function" && - typeof checkedOrDefault !== "symbol" && - !!checkedOrDefault; - - if (isHydrating) { - // Detach .checked from .defaultChecked but leave user input alone - node.checked = node.checked; - } else { - node.checked = !!initialChecked; - } - - if (disableInputAttributeSyncing) { - // Only assign the checked attribute if it is defined. This saves - // a DOM write when controlling the checked attribute isn't needed - // (text inputs, submit/reset) - if (defaultChecked != null) { - node.defaultChecked = !node.defaultChecked; - node.defaultChecked = !!defaultChecked; - } - } else { - // When syncing the checked attribute, both the checked property and - // attribute are assigned at the same time using defaultChecked. This uses: - // - // 1. The checked React property when present - // 2. The defaultChecked React property when present - // 3. Otherwise, false - node.defaultChecked = !node.defaultChecked; - node.defaultChecked = !!initialChecked; - } // Name needs to be set at the end so that it applies atomically to connected radio buttons. - - if ( - name != null && - typeof name !== "function" && - typeof name !== "symbol" && - typeof name !== "boolean" - ) { - { - checkAttributeStringCoercion(name, "name"); } - node.name = name; - } -} -function restoreControlledInputState(element, props) { - var rootNode = element; - updateInput( - rootNode, - props.value, - props.defaultValue, - props.defaultValue, - props.checked, - props.defaultChecked, - props.type, - props.name - ); - var name = props.name; - - if (props.type === "radio" && name != null) { - var queryRoot = rootNode; - - while (queryRoot.parentNode) { - queryRoot = queryRoot.parentNode; - } // If `rootNode.form` was non-null, then we could try `form.elements`, - // but that sometimes behaves strangely in IE8. We could also try using - // `form.getElementsByName`, but that will only return direct children - // and won't include inputs that use the HTML5 `form=` attribute. Since - // the input might not even be in a form. It might not even be in the - // document. Let's just use the local `querySelectorAll` to ensure we don't - // miss anything. - - { - checkAttributeStringCoercion(name, "name"); + function resetCurrentFiber() { + { + ReactDebugCurrentFrame$1.getCurrentStack = null; + current = null; + isRendering = false; + } + } + function setCurrentFiber(fiber) { + { + ReactDebugCurrentFrame$1.getCurrentStack = + fiber === null ? null : getCurrentFiberStackInDev; + current = fiber; + isRendering = false; + } + } + function getCurrentFiber() { + { + return current; + } + } + function setIsRendering(rendering) { + { + isRendering = rendering; + } } - var group = queryRoot.querySelectorAll( - 'input[name="' + - escapeSelectorAttributeValueInsideDoubleQuotes("" + name) + - '"][type="radio"]' - ); + // around this limitation, we use an opaque type that can only be obtained by + // passing the value through getToStringValue first. - for (var i = 0; i < group.length; i++) { - var otherNode = group[i]; + function toString(value) { + // The coercion safety check is performed in getToStringValue(). + // eslint-disable-next-line react-internal/safe-string-coercion + return "" + value; + } + function getToStringValue(value) { + switch (typeof value) { + case "boolean": + case "number": + case "string": + case "undefined": + return value; - if (otherNode === rootNode || otherNode.form !== rootNode.form) { - continue; - } // This will throw if radio buttons rendered by different copies of React - // and the same name are rendered into the same form (same as #1939). - // That's probably okay; we don't support it just as we don't support - // mixing React radio buttons with non-React ones. + case "object": + { + checkFormFieldValueStringCoercion(value); + } - var otherProps = getFiberCurrentPropsFromNode(otherNode); + return value; - if (!otherProps) { - throw new Error( - "ReactDOMInput: Mixing React and non-React radio inputs with the " + - "same `name` is not supported." - ); - } // If this is a controlled radio button group, forcing the input that - // was previously checked to update will cause it to be come re-checked - // as appropriate. + default: + // function, symbol are assigned as empty strings + return ""; + } + } - updateInput( - otherNode, - otherProps.value, - otherProps.defaultValue, - otherProps.defaultValue, - otherProps.checked, - otherProps.defaultChecked, - otherProps.type, - otherProps.name + function isCheckable(elem) { + var type = elem.type; + var nodeName = elem.nodeName; + return ( + nodeName && + nodeName.toLowerCase() === "input" && + (type === "checkbox" || type === "radio") ); - } // If any updateInput() call set .checked to true, an input in this group - // (often, `rootNode` itself) may have become unchecked - - for (var _i = 0; _i < group.length; _i++) { - var _otherNode = group[_i]; - - if (_otherNode.form !== rootNode.form) { - continue; - } - - updateValueIfChanged(_otherNode); - } - } -} // In Chrome, assigning defaultValue to certain input types triggers input validation. -// For number inputs, the display value loses trailing decimal points. For email inputs, -// Chrome raises "The specified value is not a valid email address". -// -// Here we check to see if the defaultValue has actually changed, avoiding these problems -// when the user is inputting text -// -// https://github.com/facebook/react/issues/7253 - -function setDefaultValue(node, type, value) { - if ( - // Focused number inputs synchronize on blur. See ChangeEventPlugin.js - type !== "number" || - getActiveElement(node.ownerDocument) !== node - ) { - if (node.defaultValue !== toString(value)) { - node.defaultValue = toString(value); - } - } -} - -var didWarnSelectedSetOnOption = false; -var didWarnInvalidChild = false; -var didWarnInvalidInnerHTML = false; -/** - * Implements an